如何在SyncAdapter onPerformSync期间正确使用AsyncTask

时间:2012-01-17 07:07:04

标签: android android-syncadapter

我收到了来自强制关闭对话框报告的用户的大量错误报告,其中包含以下内容:

java.lang.ExceptionInInitializerError
at com.MyRequest.execute(MyRequest.java:59)
at org.nsdev.MySyncAdapter.onPerformSync(MySyncAdapter.java:90)
at android.content.AbstractThreadedSyncAdapter$SyncThread.run(AbstractThreadedSyncAdapter.java:164)
  Caused by: java.lang.RuntimeException: 
  Can't create handler inside thread that has not called Looper.prepare()
at android.os.Handler.<init>(Handler.java:121)
at android.os.AsyncTask$InternalHandler.<init>(AsyncTask.java:421)
at android.os.AsyncTask$InternalHandler.<init>(AsyncTask.java:421)
at android.os.AsyncTask.<clinit>(AsyncTask.java:152)

现在,我一直试图找出如何最好地解决这个问题。在我的onPerformSync实现中,我创建了许多AsyncTasks并执行它们。我怀疑我的问题是我在从onPerformSync返回之前没有等待完成这些任务。我试着做以下事情:

Looper.prepare();

// Execute async tasks

Looper.loop();

然后我设置了一个计数器,当该计数器减少到零时,在异步任务的回调中调用Looper.myLooper()。quit()。

但是这样做会导致我的应用程序因以下运行时错误而更加崩溃:

java.lang.RuntimeException: Main thread not allowed to quit
    at android.os.MessageQueue.enqueueMessage(MessageQueue.java:175)
    at android.os.Looper.quit(Looper.java:173)
    at org.nsdev.MySyncAdapter$1.requestFinished(MySyncAdapter.java:89)
    at com.MyAsyncTask.onPostExecute(MyAsyncTask.java:84)
    at android.os.AsyncTask.finish(AsyncTask.java:417)
    at android.os.AsyncTask.access$300(AsyncTask.java:127)
    at android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:429)
    at android.os.Handler.dispatchMessage(Handler.java:99)
    at android.os.Looper.loop(Looper.java:123)
    at android.app.ActivityThread.main(ActivityThread.java:4627)
    at java.lang.reflect.Method.invokeNative(Native Method)
    at java.lang.reflect.Method.invoke(Method.java:521)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:868)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:626)
    at dalvik.system.NativeStart.main(Native Method)

知道如何正确完成同步吗?

3 个答案:

答案 0 :(得分:4)

我知道这篇文章很老,但对于遇到这个帖子的其他人来说,在主线程上不调用looper.quit()呢?以下对于我来说,SyncAdpater服务产生了几个AsyncTasks,虽然可能有其他原因不能在性能方面做到这一点......

Handler h = new Handler(Looper.getMainLooper());
            h.post(new Runnable() {
                public void run() {

                    // AsyncTask... execute();
                }
            });

答案 1 :(得分:1)

其实你做不到。 AsyncTask使用主UI线程并依赖于那里没有的Handler和Looper。使用纯Thread实现,AsyncTask只能在活动中使用。

答案 2 :(得分:0)

abloc的响应解决了这个问题,但是这个解决方案的问题是UI冻结了,这个问题出现在Android 2.2和Android 2.3中。我找到的技巧是在我的班级SyncAdapter中调用AsyncTask的构造函数并使用Looper.prepare()

/**
 * Constructor. Obtains handle to content resolver for later use.
 */
public SyncAdapter(Context context, boolean autoInitialize) {
    super(context, autoInitialize);
    mHandler = new Handler();
    //Crear un dummy AsyncTask
    new AsyncTask<Void, Void,String>() {
        @Override
        protected String doInBackground(Void... params) {
            return null;
        }
    }.execute(null,null);
}