2010-11-15 6 views
31

Je le code suivantAsyncTask et erreur Looper.prepare()

class OverlayTask extends AsyncTask<Void, Void, Void> { 
    @Override 
    public void onPreExecute() { 

     if (sites != null) { 
      myMapView.getOverlays().remove(sites); 
      myMapView.invalidate(); 
      sites = null; 
     } 
    } 

    @Override 
    public Void doInBackground(Void... unused) { 
      grabShipsWithLocation(); 
      return (null); 
    } 

    @Override 
    public void onPostExecute(Void unused) { 
     myMapView.getOverlays().add(sites); 
     myMapView.invalidate(); 
     isLoading = false; 
    } 
} 

Cela semble fonctionner très bien sur quelques appareils de test, mais je vois beaucoup d'erreurs apparaissant sur la console dev. Je n'arrive pas à comprendre pourquoi et où mettre ce Looper.prepare(). Est-ce nécessaire?

java.lang.ExceptionInInitializerError 
at com.test.appname.FinderMain$1.gotLocation(FinderMain.java:286) 
at com.test.appname.MyLocation$GetLastLocation.run(MyLocation.java:89) 
at java.util.Timer$TimerImpl.run(Timer.java:289) 
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) 

Comme demandé MyLocation.java

class GetLastLocation extends TimerTask { 
    @Override 
    public void run() { 
     lm.removeUpdates(locationListenerGps); 
     lm.removeUpdates(locationListenerNetwork); 

     Location net_loc=null, gps_loc=null; 
     if(gps_enabled) 
      gps_loc=lm.getLastKnownLocation(LocationManager.NETWORK_PROVIDER); 
     if(network_enabled) 
      net_loc=lm.getLastKnownLocation(LocationManager.GPS_PROVIDER); 

     //if there are both values use the latest one 
     if(gps_loc!=null && net_loc!=null){ 
      if(gps_loc.getTime()>net_loc.getTime()) 
       locationResult.gotLocation(gps_loc); 
      else 
       locationResult.gotLocation(net_loc); 
      return; 
     } 

     if(gps_loc!=null){ 
      locationResult.gotLocation(gps_loc); //Line 89 
      return; 
     } 
     if(net_loc!=null){ 
      locationResult.gotLocation(net_loc); 
      return; 
     } 
     locationResult.gotLocation(null); 
    } 
} 
+1

Que fait grabShipsWithLocation()? – Falmarri

+1

Quelle ligne est MyLocation.java:89? ajouter un commentaire à votre source. – blindstuff

+0

Est-ce que vous créez/démarrez l'AsyncTask à partir du thread principal? – gngr44

Répondre

95

longue histoire:

AsyncTask utilise en interne un Handler. Un gestionnaire vous permet essentiellement de publier Runnables à partir d'un autre thread sur le thread auquel le gestionnaire a été affecté, qui dans le cas de AsyncTask est toujours le thread à partir de laquelle il est appelé. Cela ne fonctionne que pour les threads qui ont un préparé, cependant.

Pour plus d'informations, voir http://developer.android.com/reference/android/os/Handler.html

histoire courte:

Enroulez chaque appel à FinderMain$1.gotLocation ou la création d'AsyncTask au sein dans un Runnable, et l'envoyer à un Handler lié au thread d'interface utilisateur , comme ceci:

class GetLastLocation extends TimerTask { 
    private Handler mHandler = new Handler(Looper.getMainLooper()); 

    @Override 
    public void run() { 
     // ... 
     mHandler.post(new Runnable() { 
      public void run() { 
       locationResult.gotLocation(null); 
      } 
     }); 
     // ... 
    } 
} 
+0

Juste la locationResult.gotLocation (null); dans la nouvelle section ou tout le lot ci-dessus? –

+0

Ou chaque locationResult.gotLocation (stuff) ?? –

+0

Tous les appels à gotLocation doivent se produire dans le thread UI, ce qui signifie dans Runnable comme ci-dessus. Vous pouvez également envelopper toute la section, mais gardez à l'esprit que cela pourrait ralentir votre interface utilisateur si son exécution prend trop de temps. Vous pouvez également placer la création AsyncTask dans gotLocation dans un Runnable comme ceci. –

18

J'ai essayé ceci ... Cela a fonctionné, j'espère que cela vous aidera ..

protected class Asyctast extends AsyncTask<String, Integer, Integer> 
{ 

    @Override 
    protected Integer doInBackground(String... params) { 
     // TODO Auto-generated method stub 


     Log.d("Asynctask", ""+params); 
Looper.prepare(); 

     ImageThumbnailsActivity m = new ImageThumbnailsActivity(); 

      Toast.makeText(ImageThumbnailsActivity.this,""+params ,Toast.LENGTH_SHORT).show(); 
      final Dialog dialog_options = new Dialog(ImageThumbnailsActivity.this); 
      dialog_options.setContentView(R.layout.option); 
      dialog_options.show(); 
     Looper.loop(); 
     return null; 
    }  
} 
+7

Ce n'est pas une bonne solution, car Looper.loop() sera bloqué pour toujours et Thread ne sera jamais fait. Vous devez utiliser Looper.myLooper(). Quit() pour éviter cela. À l'exception de cela, si vous devez appeler Looper.prepare() à partir de Thread, utilisez Thread au lieu de AsyncTask. – Borg8

+1

Enlever Looper.loop() a travaillé pour moi pour éviter la boucle infinie – jgpATs2w

Questions connexes