Pergunta

Tenho recebido um grande número de relatórios de bugs de usuários relatados em diálogos de fechamento forçado que afirmam algo como o seguinte:

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)

Agora, estou tentando descobrir a melhor forma de resolver esse problema.Dentro da minha implementação onPerformSync, estou criando uma série de AsyncTasks e as executando.Suspeito que meu problema é que não estou esperando a conclusão dessas tarefas antes de retornar do onPerformSync.Tentei fazer o seguinte:

Looper.prepare();

// Execute async tasks

Looper.loop();

E então eu configuro um contador e quando esse contador diminui para zero, chamo Looper.myLooper (). quit () dentro do retorno de chamada das tarefas assíncronas.

Mas fazer isso faz com que meu aplicativo trave ainda mais com o seguinte erro de tempo de execução:

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)

Tem alguma ideia de como realizar minha sincronização corretamente?

Foi útil?

Solução

Eu sei que esta postagem é antiga, mas para outras pessoas que se depararam com este tópico, que tal simplesmente não chamar looper.quit () no tópico principal?O seguinte funciona para mim a partir de um serviço SyncAdpater gerando várias AsyncTasks, embora possa haver outras razões para não fazer isso em termos de desempenho ...

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

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

Outras dicas

Na verdade, você não pode.AsyncTask usa a linha de execução principal da IU e depende do Handler e do Looper, que não estão disponíveis lá.Use a implementação pura de Thread, AsyncTask deve ser usado apenas nas atividades.

A resposta do abloc resolve o problema, mas o problema com esta solução é que a IU congela, esse problema está presente no Android 2.2 e Android 2.3.O truque que descobri foi invocar um construtor de AsyncTask em minha classe SyncAdapter e usar 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);
}
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top