Как правильно использовать AsyncTask во время SyncAdapter onPerformSync - PullRequest
2 голосов
/ 17 января 2012

Я получаю большое количество сообщений об ошибках от пользователей, о которых сообщалось в диалоговых окнах принудительного закрытия, в которых указано что-то вроде следующего:

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 ]

4 голосов
/ 30 сентября 2012

Я знаю, что этот пост старый, но для других, кто сталкивался с этой веткой, как насчет того, чтобы просто не вызывать looper.quit () в основной ветке? Следующее работает для меня из службы SyncAdpater, порождающей несколько AsyncTasks, хотя могут быть и другие причины не делать этого с точки зрения производительности ...

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

                    // AsyncTask... execute();
                }
            });
2 голосов
/ 23 мая 2012

На самом деле вы не можете. AsyncTask использует основной поток пользовательского интерфейса и использует Handler и Looper, которые там недоступны. Используйте чистую реализацию Thread, AsyncTask следует использовать только в действиях.

0 голосов
/ 09 января 2014

Ответ abloc решает проблему, но проблема с этим решением в том, что пользовательский интерфейс зависает, эта проблема присутствует в Android 2.2 и Android 2.3. Уловка, которую я нашел, состояла в том, чтобы вызвать конструктор AsyncTask в моем классе SyncAdapter и использовать 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);
}
...