AsyncTask和Service绑定

时间:2014-05-16 14:37:42

标签: android multithreading android-asynctask android-service android-service-binding

这是一个非常愚蠢的,这只是因为我不喜欢我的代码输出错误到logcat我问的问题。

我有一项名为BackgroundCollectorProcess的服务。它是主要的工作,它处理数据库中尚未报告的行。这是通过XMPP连接完成的。所以,在onStartCommand我有以下内容:

    @Override
    public int onStartCommand(Intent intent, int flags, int startId)
    {
        Log.d("BGCP", "Spinning");

        // Bind to our XmppConnector service to post any waiting transactions
        Intent iXmpp = new Intent(getApplicationContext(), BackgroundXmppConnector.class);
        bindService(iXmpp, mConnection, Context.BIND_AUTO_CREATE);      

        // Start the sending of all collected logs
        new DeliveriesSenderTask().execute();
        new GeoLogSenderTask().execute();

        /*
            WARNING!!

            You can't call unbindService(mConnection) here - as the two main threads
            for posting delivery and geolocation transactions wont have completed in
            time. Thus, leaving this object unable to complete it's task.

            Logcat will throw up an "error" - saying about a resource binding being
            leaked in this class. 

            TODO: Revisit this once there is a definitive answer to the problem.
         */

        // Commit suicide. BackgroundCollectorKicker will ressurect me. 
        stopSelf();

        return Service.START_NOT_STICKY;
    }

正如你可以通过我的大量文本墙看到的评论,我遇到了一个愚蠢的logcat错误。这是:

05-16 15:30:26.243: E/ActivityThread(16078): Service com.goosesys.gaggle.services.BackgroundCollectorProcess has leaked ServiceConnection com.goosesys.gaggle.services.BackgroundCollectorProcess$1@449ddff0 that was originally bound here
05-16 15:30:26.243: E/ActivityThread(16078): android.app.ServiceConnectionLeaked: Service com.goosesys.gaggle.services.BackgroundCollectorProcess has leaked ServiceConnection com.goosesys.gaggle.services.BackgroundCollectorProcess$1@449ddff0 that was originally bound here
05-16 15:30:26.243: E/ActivityThread(16078):    at android.app.LoadedApk$ServiceDispatcher.<init>(LoadedApk.java:969)
05-16 15:30:26.243: E/ActivityThread(16078):    at android.app.LoadedApk.getServiceDispatcher(LoadedApk.java:863)
05-16 15:30:26.243: E/ActivityThread(16078):    at android.app.ContextImpl.bindService(ContextImpl.java:1507)
05-16 15:30:26.243: E/ActivityThread(16078):    at android.app.ContextImpl.bindService(ContextImpl.java:1496)
05-16 15:30:26.243: E/ActivityThread(16078):    at android.content.ContextWrapper.bindService(ContextWrapper.java:473)
05-16 15:30:26.243: E/ActivityThread(16078):    at com.goosesys.gaggle.services.BackgroundCollectorProcess.onStartCommand(BackgroundCollectorProcess.java:70)
05-16 15:30:26.243: E/ActivityThread(16078):    at android.app.ActivityThread.handleServiceArgs(ActivityThread.java:2681)
05-16 15:30:26.243: E/ActivityThread(16078):    at android.app.ActivityThread.access$1900(ActivityThread.java:146)
05-16 15:30:26.243: E/ActivityThread(16078):    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1337)
05-16 15:30:26.243: E/ActivityThread(16078):    at android.os.Handler.dispatchMessage(Handler.java:99)
05-16 15:30:26.243: E/ActivityThread(16078):    at android.os.Looper.loop(Looper.java:137)
05-16 15:30:26.243: E/ActivityThread(16078):    at android.app.ActivityThread.main(ActivityThread.java:5171)
05-16 15:30:26.243: E/ActivityThread(16078):    at java.lang.reflect.Method.invokeNative(Native Method)
05-16 15:30:26.243: E/ActivityThread(16078):    at java.lang.reflect.Method.invoke(Method.java:511)
05-16 15:30:26.243: E/ActivityThread(16078):    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:797)
05-16 15:30:26.243: E/ActivityThread(16078):    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:564)
05-16 15:30:26.243: E/ActivityThread(16078):    at dalvik.system.NativeStart.main(Native Method)

这些是AsyncTasks:

    private class DeliveriesSenderTask extends AsyncTask<Void, Void, Void>
    {
        @Override
        protected Void doInBackground(Void... arg0) 
        {
            try
            {
                doPostDeliveries();
            }
            catch(Exception ex)
            {
                Utility.writeExceptionToLog(getApplicationContext(), ex);
            }           
            return null;
        }       
    }

    private class GeoLogSenderTask extends AsyncTask<Void, Void, Void>
    {

        @Override
        protected Void doInBackground(Void... params) 
        {       
            try
            {
                doPostGeoLogs();
            }
            catch(Exception ex)
            {
                Utility.writeExceptionToLog(getApplicationContext(), ex);
            }
            return null;
        }       
    }

现在,鉴于要自行运行的任务(或可能)非常耗时,它们必须在不同的线程中运行。所以,我不能再调用unbindService(),因为线程还没有完成。

我的问题是......什么时候最好拨打unbindService?显然,我已经尝试在GeoLogSenderTask完成后调用它,但我仍然得到LogCat输出这个愚蠢的消息,因为主线程将在两个asynctasks之前完成。

非常感谢任何帮助。感谢。

1 个答案:

答案 0 :(得分:1)

将asyncTask实例保存为成员变量。 在两个AsyncTask实现中引入onPostExecute方法,并在两个方法中检查其他任务是否已完成AsyncTask.getStatus == AsyncTask.Status.FINISHED。 当另一个完成后,请拨打该服务的stopSelf()

 protected void onPostExecute(Result result) {
    if(otherTask.getStatus() == AsyncTask.Status.FINISHED) {
      stopSelf();
    }
  };