Update UI from an event with a thread

Posted by tyrone-tudehope on Stack Overflow See other posts from Stack Overflow or by tyrone-tudehope
Published on 2010-03-26T08:48:52Z Indexed on 2010/03/26 8:53 UTC
Read the original article Hit count: 307

Filed under:

Im working on a small application to try out an idea that I have. The idea is to periodically update the UI when event of some sort occurs. In the demo I've created, I'm updating a ProgressDialog every 2 seconds for 15 turns.

The problem I am having, which I don't quite understand is that when an event is handled, I send a message to the handler which is supposed to update the message in the ProgressDialog. When this happens however, I get an exception which states that I can't update the UI from that thread.

The following code appears in my Activity:

ProgressDialog diag;
String diagMessage = "Started loading...";

final static int MESSAGE_DATA_RECEIVED = 0;
final static int MESSAGE_RECEIVE_COMPLETED = 1;


final Handler handler = new Handler(){
    @Override
    public void handleMessage(Message msg){
        diag.setMessage(diagMessage);

        switch(msg.what){
            case MESSAGE_DATA_RECEIVED:

                break;
            case MESSAGE_RECEIVE_COMPLETED:
                dismissDialog();
                killDialog();
                break;
        }
    }
};

Boolean isRunning = false;

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

    setupDialog();
    if(isRunning){
        showDialog();
    }

    setContentView(R.layout.main);


}

void setupDialog(){
    if(diag == null){
        diag = new ProgressDialog(ThreadLoading.this);
        diag.setMessage(diagMessage);
    }
}

void showDialog(){
    isRunning = true;
    if(diag != null && !diag.isShowing()){
        diag.show();
    }
}

void dismissDialog(){
    if(diag != null && diag.isShowing()){
        diag.dismiss();
    }
}

void killDialog(){
    isRunning = false;
}

public void onStart(){
    super.onStart();

    showDialog();



    Thread background = new Thread(new Runnable(){
        public void run(){
            try{
                final ThreadRunner tr = new ThreadRunner();
                tr.setOnDataReceivedListener(new ThreadRunner.OnDataReceivedListener(){
                    public void onDataReceived(String message){
                        diagMessage = message;
                        handler.handleMessage(handler.obtainMessage(MESSAGE_DATA_RECEIVED));
                    }
                });

                tr.setOnDataDownloadCompletedEventListener(new ThreadRunner.OnDataDownloadCompletedListener(){
                    public void onDataDownloadCompleted(String message){
                        diagMessage = message;
                        handler.handleMessage(handler.obtainMessage(MESSAGE_RECEIVE_COMPLETED));
                    }
                });

                tr.runProcess();
            }
            catch(Throwable t){
                throw new RuntimeException(t);
            }
        }
    });

    background.start();
}

@Override
public void onPause(){
    super.onPause();
    dismissDialog();
}

For curiosity sake, here's the code for the ThreadRunner class:

public interface OnDataReceivedListener {
    public void onDataReceived(String message);
}

public interface OnDataDownloadCompletedListener {
    public void onDataDownloadCompleted(String message);
}

private OnDataReceivedListener onDataReceivedEventListener;
private OnDataDownloadCompletedListener onDataDownloadCompletedEventListener;


int maxLoop = 15;
int loopCount = 0;
int sleepTime = 2000;

public void setOnDataReceivedListener(OnDataReceivedListener onDataReceivedListener){
    this.onDataReceivedEventListener = onDataReceivedListener;
}

public void setOnDataDownloadCompletedEventListener(OnDataDownloadCompletedListener onDataDownloadCompletedListener){
    this.onDataDownloadCompletedEventListener = onDataDownloadCompletedListener;
}

public void runProcess(){
    for(loopCount = 0; loopCount < maxLoop; loopCount++){
        try{
            Thread.sleep(sleepTime);
            onDataReceivedEventListener.onDataReceived(Integer.toString(loopCount));
        }
        catch(Throwable t){
            throw new RuntimeException(t);
        }
    }

    onDataDownloadCompletedEventListener.onDataDownloadCompleted("Download is completed");
}

Am I missing something? The logic makes sense to me and it looks like everything should work, I'm using a handler to update the UI like it is recommended.

Any help will be appreciated.

Thanks, Tyrone

P.S. I'm developing for Android 1.5

© Stack Overflow or respective owner

Related posts about android