2010-11-22 15 views
0

Je semble avoir des problèmes avec la mise à jour d'un TextView à partir d'un thread. J'ai une classe GameConnection (qui gère une connexion socket) que je veux utiliser à travers les activités. Il appelle un "onMessage" local, qui utilise ensuite le gestionnaire cible pour appeler le message d'envoi. Le "gestionnaire" dans ce cas, est dans mon activité GameBrowser.Essayer de mettre à jour un objet TextField via un gestionnaire et obtenir CalledFromWrongThreadException

Voici le code de la classe GameConnection. Comme mentionné ci-dessus, un procédé local "onMessage" traite la répartition du message.

private void onMessage(String message){ 
     ... // create message from String 
     handler.dispatchMessage(msg); 
    } 

Cependant, quand je reçois la réponse dans la classe GameBrowser, je reçois un CalledFromWrongThreadException. Initialement, j'utilisais une méthode de rappel, qui bien sûr ne fonctionnait pas. Donc, après quelques recherches, j'ai trouvé que je devais utiliser un Handler, mais je n'arrive pas à le faire correctement.

public class GameBrowser extends Activity { 

@Override 
protected void onCreate(Bundle savedInstanceState) { 

    super.onCreate(savedInstanceState); 
    Log.d(C.tag, "GameBrowser.onCreate addr:" + this); 

    handler = new Handler(new HandlerCallback()); 

    connection.addMessageListener(handler); 
    connection.connect(); 
    txtGameLabel = (TextView)findViewById(R.id.txtGamesLabel); 
    setContentView(R.layout.game_browser); 


} 

private class HandlerCallback implements Callback{ 

    @Override 
    public boolean handleMessage(Message msg) { 

     if (txtGameLabel == null){ 
      txtGameLabel = (TextView)findViewById(R.id.txtGamesLabel); 
     } 

     String message = msg.getData().getString("message"); 

     Log.d(C.tag, "GameBrowser recieved message " + message); 

     txtGameLabel.setText("Data: " + message); 

     return true; 
    } 
} 

} 

Répondre

0

J'ai compris ce que je faisais mal. Au lieu d'appeler le gestionnaire à partir du thread socket, j'ai utilisé un rappel, puis utilisé Runnable pour publier sur le gestionnaire dans la classe GameConnection. Lorsque onMessage exécute "run", qui exécute "updateTextField", nous sommes de retour dans le thread principal.

@Override 
public void onMessage(final String message) { 

    handler.post(new Runnable(){ 
     @Override 
     public void run() { 
      updateTextField(message); 

     } 
    }); 

} 

private void updateTextField(String message){ 
    if (txtGameLabel == null) 
     txtGameLabel = (TextView)findViewById(R.id.txtGamesLabel); 

    txtGameLabel.setText(message); 
}