Updating the UI in native mode with an on-stream handler (Android)

I am trying to make multiple connections in a classroom and update multiple progress bars on the main screen.

But I have the following error when trying to use thread in android: Code: 05-06 13: 13: 11.092: ERROR / ConnectionManager (22854): ERROR: Cannot create a handler inside a thread that did not call Looper.prepare ()

Here is a small section of my code in the main activity

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(); } 
 } 
}

      

And my connectionManager class:

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); 
 }
}

      

Failure errors occur on the first line "case DIALOG_PROGRESS_NETWORK:". My first progress bar is hidden, but the second is not visible.

I think I did something wrong using streams and handlers, but I don't know why.

At first I used handler.sendMessage instead of handler.handleMessage, but when I had multiple tasks in my connection manager, the progress indicator only updated at the end of all tasks.

Thanks in advance for your help

+2


a source to share


3 answers


Make it Handler handler

unfinal and run it inside onCreate()

.



+5


a source


Having a final handler and declaring it in the class definition is great. Also, in your last piece of code, when you initialize a handler in onCreate, you are actually "shadowing" the handler declared in your class, so you don't initialize it. I'm very surprised that you didn't have a NullPointerException.

But in ConnectionManager :: updateProgressBar, you really need to call sendMessage (), because by calling handleMessage () directly, the handler is called from the ConnectionManager :: updateProgressBar thread (which is probably not the UI thread).



I'm not sure what caused you problems with updating the progress bars only once, but this is definitely a logic error somewhere. Try registering at different stages of your application. before sending a message and while processing it -.

+3


a source


Hrk, the shadow part is when you declare a local variable inside a method with the same name as the field:

Handler handler = ...

      

To use this field, omit the type:

handler = ...

      

As for the exception, just create the objects ProgressDialog

on the main thread (for example in the onCreate () method) and call one of the show () methods later.

0


a source







All Articles