Domanda

Ho ricevuto un gran numero di segnalazioni di bug da utenti segnalati da finestre di dialogo di chiusura forzata che affermano qualcosa di simile al seguente:

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)

Ora, ho cercato di capire come dovrei risolvere al meglio questo problema.All'interno della mia implementazione di onPerformSync sto creando una serie di AsyncTask e li sto eseguendo.Sospetto che il mio problema sia che non sto aspettando il completamento di queste attività prima di tornare da onPerformSync.Ho provato a fare quanto segue:

Looper.prepare();

// Execute async tasks

Looper.loop();

E poi ho impostato un contatore e quando quel contatore scende a zero, chiama Looper.myLooper (). quit () all'interno del callback dalle attività asincrone.

Ma in questo modo la mia applicazione si arresta in modo ancor più grave con il seguente errore di runtime:

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)

Qualche idea su come eseguire correttamente la mia sincronizzazione?

È stato utile?

Soluzione

So che questo post è vecchio, ma per gli altri che si imbattono in questo thread, che ne dici di non chiamare looper.quit () sul thread principale?Quanto segue funziona per me da un servizio SyncAdpater che genera diversi AsyncTask, sebbene potrebbero esserci altri motivi per non farlo in termini di prestazioni ...

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

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

Altri suggerimenti

In realtà non puoi.AsyncTask utilizza il thread dell'interfaccia utente principale e si basa su Handler e Looper che non sono disponibili lì.Usa pura implementazione Thread, AsyncTask dovrebbe essere usato solo nelle attività.

La risposta di abloc risolve il problema, ma il problema con questa soluzione è che l'interfaccia utente si blocca, questo problema è presente in Android 2.2 e Android 2.3.Il trucco che ho trovato è stato richiamare un costruttore di AsyncTask nella mia classe SyncAdapter e utilizzare 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);
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top