2010-11-09 6 views
0

Donc, j'obtiens une erreur que je mets à jour l'interface utilisateur du mauvais thread. Ce n'était bien sûr pas mon intention. Mon cas est assez long, mais je vais essayer de le rendre justice avec des extraits de code. Mon but final est d'exécuter une tâche coûteuse dans un thread séparé et de poster une mise à jour qui se produit en cours de route et à la fin de ma liste.Comment faire pour mettre à jour l'interface utilisateur via Handler

public class test extends Activity { 

    private ArrayAdapter<String> _mOutArrayAdapter; 
    private ListView _mOutView; 
    private EditText _mCmdEditText; 
    private Button _mRunButton; 
    private Interpreter _interpreter; 

    // Need handler for callbacks to the UI thread 
    public final Handler _mHandler = new Handler() { 
    public void handleMessage(Message msg) { 
     _mOutArrayAdapter.add(msg.getData().getString("text")); 
    }; 
    }; 

    // Create runnable for posting 
    final Runnable mUpdateResults = new Runnable() { 
     public void run() { 
      updateResultsInUi(); 
     } 
    }; 

    /** Called when the activity is first created. */ 
    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.main); 

     _interpreter = new Interpreter(true); 

     _mOutView = (ListView)findViewById(R.id.out); 
     _mCmdEditText = (EditText)findViewById(R.id.edit_command); 
     _mRunButton = (Button)findViewById(R.id.button_run); 

     _mOutArrayAdapter = new ArrayAdapter<String>(this, R.layout.message); 
     _mOutView.setAdapter(_mOutArrayAdapter); 
     _mOutArrayAdapter.clear(); 
     _interpreter.setOutputAdapter(_mOutArrayAdapter); 

     Thread t = new Thread() { 
      public void run() { 
       _mResults = _interpreter.executeExpression("startup;",_mHandler); 
       _mHandler.post(mUpdateResults); 
      } 
     }; 
     t.start(); 

    ); 

Et puis à l'intérieur inpterpreter Je fais ceci:

public class Interpreter 
{ 

    private static Handler _mHandler; 

    public String executeExpression(String expression, Handler handler) 
    { 
     _mHandler = handler; 

     //Do a bunch of stuff that sometimes calls displayText from this class or from others 

     return answer; 
    } 

    public void displayText(String text) 
    { 
     Message msg = new Message(); 
     Bundle bndl = new Bundle(); 
     bndl.putString("text", text); 
     msg.setData(bndl); 
     _mHandler.dispatchMessage(msg); 
    } 
} 

L'affichage des œuvres de réponse finale. Et le dispatchMessage finit par déclencher handleMessage, mais il jette une erreur que je ne peux pas modifier l'interface utilisateur en dehors du thread d'interface utilisateur que je sais est illégal. Alors, qu'est-ce que je fais de mal?

Merci!

+0

Essayez d'utiliser Async Tâche et comme d'autres ont dit, pas sûr de ce que fait votre code – jonney

+0

Vous avez raison, sendMessage est utilisé pour envoyer des messages qui sont reçus dans handleMessage de gestionnaire. –

Répondre

2

Je vous suggère fortement de vous en tenir à un AsyncTask (ou à l'une des versions droid-fu si vous avez besoin d'un support de rotation/arrière-plan) à moins de savoir dans quoi vous vous engagez. Il vous aidera à garder une trace claire du code qui est en cours d'exécution dans votre thread UI et quel code est dans la tâche d'arrière-plan, et vous épargner beaucoup de confusion que vous pouvez causer avec Thread s et Handler s. DispatchMessage() provoque l'exécution du gestionnaire sur l'unité d'exécution actuelle.

+0

J'ai examiné les compromis avec AsyncTasks vs. Threads. Savez-vous pourquoi l'exemple montré ne fonctionne pas? – corbin

+0

Votre code est assez salissant, nous ne pouvons vraiment pas dire ce qui se passe là-bas. Au moins, je ne peux pas – Falmarri

+1

Je m'en tiens au fil pour plusieurs raisons. J'espérais qu'un exemple plus simple fonctionnerait pour obtenir de l'aide. Mon problème était d'appeler dispatchMessage au lieu de sendMessage ... oops – corbin

3
_mHandler.dispatchMessage(msg); 

http://developer.android.com/reference/android/os/Handler.html

DispatchMessage (message msg)

messages système Handle ici.

Vous devez utiliser _mHandler.sendMessage(msg); Il mettra le message dans la file d'attente à exécuter par le thread qui a déclaré le gestionnaire.

SendMessage (message msg)

Pousse un message sur l'extrémité de la file de messages une fois que tous les messages en attente avant l'heure actuelle.

+0

envoi! = Envoi ... quelle distinction évidente/s.Ce ne sont que des heures perdues de mon temps pour découvrir pourquoi mon gestionnaire ne travaillait pas. Merci Chris. – GDanger

1

La méthode de post-traitement de Handler nécessite un objet Runnable dans le paramètre et l'ordonnancement de l'exécution de ce bloc exécutable. Au lieu de cela, vous pouvez utiliser Handler.sendEmptyMessage() ou Handler.sendMessage() pour envoyer un message à Handler. changer SO votre code à suivre:

Thread t = new Thread() { 
      public void run() { 
       _mResults = _interpreter.executeExpression("startup;",_mHandler); 
       Message msg= _mHandler.obtainMessage(); 
       msg.obj= _mResults; 
       _mHandler.sendMessage(msg); 
      } 
     }; 
Questions connexes