2010-05-09 11 views
2

J'essaie d'établir plusieurs connexions dans une classe et de mettre à jour la barre de progression multiple dans l'écran principal.Mise à jour de l'interface utilisateur dans l'activité principale via le gestionnaire d'un thread (Android)

Mais j'ai l'erreur suivante en essayant d'utiliser le fil dans Android: code: 05-06 13: 13: 11,092: ERREUR/ConnectionManager (22854): ERREUR: Impossible de créer handler filetage intérieur qui a pas appelé Looper.prepare()

Voici une petite partie de mon code dans la principale activité

public class Act_Main extends ListActivity 
{ 
private ConnectionManager cm; 

public void onCreate(Bundle savedInstanceState) 
{ 
     super.onCreate(savedInstanceState); 

     // Set up the window layout 
     requestWindowFeature(Window.FEATURE_CUSTOM_TITLE); 
     setContentView(R.layout.main); 
     getWindow().setFeatureInt(Window.FEATURE_CUSTOM_TITLE, R.layout.custom_title); 
} 

public void startConnection() 
{ 
     //open DB connection 
     db = new DBAdapter(getApplicationContext()); 
     db.open(); 

     cm = new ConnectionManager(handler, db); 
     showDialog(DIALOG_PROGRESS_LOGIN); 
} 

@Override 
public void onStart() 
{ 
     super.onStart(); 
     startConnection(); 
} 

protected Dialog onCreateDialog(int id) 
{ 
     switch (id) 
     { 
     case DIALOG_PROGRESS_LOGIN: 
      progressDialog = new ProgressDialog(Act_Main.this); 
      progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL); 
      progressDialog.setMessage("Connecting.\nPlease wait..."); 
      progressThreadLogin = new ProgressThreadLogin(); 
      progressThreadLogin.start(); 

      return progressDialog; 
     case DIALOG_PROGRESS_NETWORK: 
      [b]progressDialog = new ProgressDialog(Act_Main.this);[/b] 
      progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL); 
      progressDialog.setMessage("Loading entire network.\nPlease wait..."); 
      progressThreadNetwork = new ProgressThreadNetwork(); 
      progressThreadNetwork.start(); 

      return progressDialog; 
     default: 
      return null; 
     } 
} 


// Define the Handler that receives messages from the thread and update the progress 
final Handler handler = new Handler() 
{ 
     public void handleMessage(Message msg) 
     { 
      int total = msg.getData().getInt("total"); 
      int step = msg.getData().getInt("step"); 

      Log.d(TAG, "handleMessage:PROCESSBAR:"+total); 
      progressDialog.setProgress(total); 

      if (total >= 100) 
      { 
       switch (step) 
       { 
        case UPDATE_NETWORK: 
          dismissDialog(DIALOG_PROGRESS_LOGIN); 
          showDialog(DIALOG_PROGRESS_NETWORK); 
          cm.getNetwork(); 
          break; 
            .... 
        default: 
          break; 
       } 
      } 
     } 
}; 

private class ProgressThreadLogin extends Thread 
{ 
     ProgressThreadLogin() { } 
     public void run() { cm.login(); } 
} 

private class ProgressThreadNetwork extends Thread 
{ 
     ProgressThreadNetwork() { } 
     public void run() { cm.getNetwork(); } 
} 
} 

Et ma classe ConnectionManager:

public class ConnectionManager 
{ 
public ConnectionManager(Handler handler, DBAdapter db) 
{ 
     this.handler = handler; 
     this.db = db; 
} 

public void updateProgressBar(int step, int value) 
{ 
     if (value == 0) 
      total = total+1; 
     else 
      total = value ; 

     Message msg = handler.obtainMessage(); 
      Bundle b = new Bundle(); 
      b.putInt("total", total); 
      b.putInt("step", step); 
      msg.setData(b); 
      handler.handleMessage(msg); 
} 

public void login() 
{ 
      //DO MY LOGIN TASK 
     updateProgressBar(Act_Main.UPDATE_NETWORK, 100); 
} 
} 

Les erreurs de plantage se produisent sur la première ligne de "case DIALOG_PROGRESS_NETWORK:". Ma première barre de progression est masquée mais la seconde n'est pas affichée.

Je pense que j'ai fait quelque chose de mal en utilisant les threads et les gestionnaires, mais je ne sais pas pourquoi.

J'ai d'abord utilisé handler.sendMessage à la place de handler.handleMessage mais lorsque j'avais plusieurs tâches dans connectionManager, la barre de progression n'était mise à jour qu'à la fin de toutes les tâches.

Nous vous remercions d'avance pour votre aide

Répondre

5

Faire Handler handler non-finale et init à l'intérieur onCreate().

+1

Ceci est correct. Vous ne pouvez pas appeler 'new Handler()' dans votre définition de classe (ce n'est même pas correct, vous pouvez seulement initialiser un objet * static * dans la définition de la classe). De plus, il n'y a aucune raison que ce soit définitif. Un gestionnaire est lié au thread dans lequel il a été créé et ce thread doit exécuter une file d'attente de messages/looper. Le placer dans 'onCreate()' est la bonne façon d'attacher votre gestionnaire au thread principal de l'interface utilisateur. – stormin986

+8

@ stormin986 Vous avez tort ..Nous pouvons certainement appeler la nouvelle méthode si nous voulons (mais ce que l'on dit être une mauvaise pratique) ensuite vous avez dit "vous ne pouvez initialiser un objet statique dans la définition de classe" vous avez tort, nous pouvons initialiser n'importe quelle variable définition ... – aProgrammer

3

Avoir le gestionnaire final et le déclarer dans la définition de classe est parfaitement bien. De plus, dans votre dernier extrait de code lorsque vous initialisez votre gestionnaire dans onCreate, vous êtes en train d'observer le gestionnaire déclaré dans votre classe, donc vous ne l'initialisez pas. Je suis assez surpris que vous n'ayez eu aucune exception NullPointerException. Mais dans ConnectionManager :: updateProgressBar vous devez vraiment appeler sendMessage() car en appelant directement handleMessage(), le gestionnaire est appelé depuis le thread de ConnectionManager :: updateProgressBar (qui n'est probablement pas le thread UI).

Je ne suis pas sûr de ce qui vous a causé le problème de mettre à jour les barres de progression une seule fois, mais c'est sûrement un bug de logique quelque part. Essayez de vous connecter à différentes étapes de votre application. avant d'envoyer le message, et en le manipulant.

0

Hrk, la partie shadowing est lorsque vous déclarez une variable locale dans la méthode qui a le même nom que le champ:

Handler handler = ... 

Pour utiliser le champ, omettez le type:

handler = ... 

En ce qui concerne l'exception, instanciez simplement les objets ProgressDialog dans le thread principal (par exemple, dans la méthode onCreate()) et appelez l'une de ses méthodes show() plus tard.

Questions connexes