Pregunta

He estado recibiendo una gran cantidad de informes de errores de usuarios informados de los cuadros de diálogo de cierre forzado que indican algo como lo siguiente:

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)

Ahora, he intentado averiguar cuál es la mejor forma de resolver este problema.Dentro de mi implementación onPerformSync, estoy creando una serie de AsyncTasks y ejecutándolas.Sospecho que mi problema es que no estoy esperando a que se completen estas tareas antes de regresar de onPerformSync.Intenté hacer lo siguiente:

Looper.prepare();

// Execute async tasks

Looper.loop();

Y luego configuro un contador y cuando ese contador disminuye a cero, llamo a Looper.myLooper (). quit () dentro de la devolución de llamada desde las tareas asíncronas.

Pero hacer esto hace que mi aplicación se bloquee aún más con el siguiente error de tiempo de ejecución:

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)

¿Alguna idea de cómo realizar correctamente mi sincronización?

¿Fue útil?

Solución

Sé que esta publicación es antigua, pero para otras personas que se encuentran con este hilo, ¿qué tal si no llaman a looper.quit () en el hilo principal?Lo siguiente funciona para mí desde un Servicio SyncAdpater que genera varias AsyncTasks, aunque puede haber otras razones para no hacer esto en términos de rendimiento ...

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

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

Otros consejos

En realidad, no puedes.AsyncTask usa el hilo principal de la interfaz de usuario y se basa en Handler y Looper, que no está disponible allí.Use la implementación de Thread pura, AsyncTask debe usarse solo en las actividades.

La respuesta de abloc soluciona el problema, pero el problema con esta solución es que la UI se congela, este problema está presente en Android 2.2 y Android 2.3.El truco que encontré fue invocar un constructor de AsyncTask en mi clase SyncAdapter y usé 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 bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top