使用Singleton模式同步HTTP请求

时间:2014-08-19 17:37:45

标签: android multithreading http singleton intentservice

我尝试(在Android应用程序中)使用单例模式将我的主线程与向服务器发出http请求的目标服务同步。我无法理解正确的实现,并想知道我是否可以在正确的方向上找到一些指示。

所以,这是来自主线程的http请求的示例用法:

Intent intent = new Intent(getActivity(), ClientService.class);
intent.putExtra(ClientService.REQUEST, ClientService.CLIENT_LIST_REQ);
SyncManager syncManager = SyncManager.getInstance(getActivity());
syncManager.submitHttpRequest(intent);
Log.d(TAG, syncManager.getResponse());

这是SyncManager的单例,我承认这是从我早期的一个主题的解决方案中找到的:Thread Synchronization with IntentService(Vladimir Lichonos的解决方案)。

public class SyncManager {

    private static SyncManager instance;
    private Object Lock;
    private boolean hasReturned;
    private String response;
    public Context mContext;
    LinkedList<OnCompletionListener> mListeners;

    private SyncManager(Context c){
        mContext = c;
        mListeners = new LinkedList<OnCompletionListener>();
        hasReturned = false;
    }

    public static SyncManager getInstance(Context c) {
        if(instance == null){
            synchronized (SyncManager.class){
                if(instance == null){
                    instance = new SyncManager(c.getApplicationContext());
                }
            }
        }
        return instance;
    }

    //to be called by the activity/fragment
    public void submitHttpRequest(Intent intent){
        mContext.startService(intent);
    }

    public boolean checkHasReturned(){
        synchronized(Lock){
            return hasReturned;
        }
    }

    public void setReturnFlag(){
        synchronized(Lock){
            hasReturned = true;
        }
    }

    public void resetReturnFlag(){
        synchronized(Lock){
            hasReturned = false;
        }
    }

    public void setResponse(String response){
        synchronized(Lock){
            this.response = response;
        }
    }

    public String getResponse(){
        synchronized(Lock){
            return response;
        }
    }

    public void addListener(OnCompletionListener listener){
        synchronized(mListeners){
            mListeners.add(listener);
        }
    }

    public void removeListener(OnCompletionListener listener){
        synchronized(mListeners){
            mListeners.remove(listener);
        }
    }


    //to be called by the service
    public void HttpRequestComplete(){
        synchronized(mListeners){
            for (OnCompletionListener listener : mListeners){
                listener.onCompleted(this);
            }
        }
    }


    public static interface OnCompletionListener{

        public void onCompleted(SyncManager instance);

    }
}

关于监听器的所有内容都来自原始解决方案(并且目前在代码中未使用),我并不真正理解如何使用它们,但我觉得这可能是纠正实现的关键。关于返回标志和响应的所有内容都是我的,它们目前无法正常工作。

以下是ClientService的重要部分:

protected void onHandleIntent(Intent intent) {
    SyncManager syncManager = SyncManager.getInstance(getApplicationContext());
    Log.d(TAG, "entered onHandleIntent");
    int rqst = intent.getIntExtra(REQUEST, DEFAULT_REQ);
    Log.d(TAG, ""+rqst);
    String response = "";
    switch(rqst){
        case ABOUT_REQ: 
            response = getAbout();
            break;
        case VER_DATA_REQ:
            response = getVerificationData("douglas_adams_uri");
            break;
        case CLIENT_LIST_REQ:
            response = getClientList();
            break;
    }
    syncManager.setResponse(response);
    syncManager.setReturnFlag();
    return;
}

摘要:

所以,您可能会从示例调用中注意到,我希望能够做的是进行HTTP调用,然后在返回该调用后,访问数据(现在我和#39;在Log.d函数中获得空指针异常,因为在http请求返回后可以填充&#39; respose&#39;变量之前调用该语句。因此,一旦服务启动,我想阻止启动它的线程,然后在服务停止运行后取消阻止它。在早期的帖子中作为答案给出的示例单例结构似乎很有希望,但我不知道如何实现包含的侦听器部分。相反,我试图在单个变量上设置 synchronized ,因此SyncManager代码的部分与侦听器无关,但是不起作用。寻找有关如何实现单例模式的更多见解,以实现我在目标服务进行http调用时阻止主线程的目标。

我意识到我的一些措辞可能看起来过于重复,但我非常努力地成为过去贬低的特定b / c。

1 个答案:

答案 0 :(得分:2)

您不需要任何单身人士来实现您的目标。使用AsyncTask,请参阅文档here。基本上你需要覆盖在后台线程上执行的doInBackground()方法;在这里,您将实施HTTPRequest投放。后台线程将一直等到它从服务器获得响应(或超时),并通过调用onPostExecute()将结果提供给主线程,您可以在其中实现如何处理结果。