How to pass progress value from thread to activity?

3.8k views Asked by At

I am having a design issue sending progress bar value from class called from a Thread in Activity class to update the GUI, as the following

[The code snippet don't compile it's for explaining only]:

Class A : Extend Activity {
  new Thread(new Runnable() 
    {
       public void run() 
       {
            B objB = new B();
            objB.DownloadFile();
        }
    }).start();
}

Class B {
    public void DownloadFile()
    {
       ... some work [preparing SOAP request]
       while(response.read())
       {
         //send calculated progress to Class A to update the progress value
       }

    }

}

Any help or guide would be greatly appreciated

3

There are 3 answers

2
Rutger On BEST ANSWER

You could make an updateProgressBar method in class A and then pass class B a reference to class A. Class B could then call the callback function in A (probably pass an int or something to indicate how far the progress is). Updating the UI from a different thread then the UI thread tends to cause problems. Luckily the Activity class has the method "runOnUiThread(Runnable action)". So to set the progress you could do something like:

while(response.read()){
  //do stuff here
int progress = getProgress(); //set the progress to something
  a.runOnUiThread(new Runnable(){
    a.updateProgress(progress);
  });
}
1
dave.c On

I've used a Handler to achieve this effect. Create it in the Activity that you create the ProgressDialog in, then pass the Handler into the maethod you want to get the progress from. Then you can send a message back to the calling Activity to update the progress:

public class ClassA extends Activity {
    ...
    private static final int HANDLER_MESSAGE_PERFORM_DIALOG_UPDATE = 0;
    ...
    new Thread(new Runnable() 
    {
        public void run() 
        {
            B objB = new objB();
            objB.DownloadFile(handler);
        }
    }).start();
    ...
    private Handler handler = new Handler(){
        @Override
        public void handleMessage(Message msg) {
            switch(msg.what){
            case Constants.HANDLER_MESSAGE_PERFORM_DIALOG_UPDATE:
                progress.setProgress(msg.arg1);
                break;
            default:
                Log.w("TAG_NAME","handleMessage / Message type not recognised / msg.what = "+String.valueOf(msg.what));
            }
        }
    };
}

Class B 
{
    public void DownloadFile(Handler handler)
    {
       ... some work [preparing SOAP request]
       while(response.read())
       {
         //send calculated progress to Class A to update the progress value
           sendMessage(handler,HANDLER_MESSAGE_PERFORM_DIALOG_UPDATE,progress);
       }
    }
    private void sendMessage(Handler handler,int what, int arg1){
        Message msg = Message.obtain();
        msg.what = what;
        msg.arg1 = arg1;
        handler.sendMessage(msg);
    }
}
0
Nixit Patel On

I always use this kind of pattre and works gr8 for me...

class A{
    new Thread(new Runnable() 
    {   
            public void run() 
            {
            B objB = new B(new ListnerClass());
            objB.DownloadFile();
            }
    }).start();

    class ListnerClass implements B.ValueListner{
        update(int v){
            doWork();
        }
    }


}

class B{

    ValueListner listner;

    interface ValuListner{
        update(int i);
    }
    B(ValueListner listner){
        this.listner = listner;
    }
    public void DownloadFile()
        {
            ... some work [preparing SOAP request]
        while(response.read())
        {
            listner.update(value);
        }

    }
}