Search code examples
javaandroidmultithreadingrunnablefinal

Set boolean from outside Thread, inside the Thread-run


I've got a boolean outside the Thread. Then I use a method that requires a Thread around it that returns a boolean. How can I set the boolean outside the thread with the returned boolean?

Code:

// Handle Automatic E-Mail Sending in a new Thread
new Thread(new Runnable() {
    @Override
    public void run() {
        // Since we want to display a Toast from within a different Thread,
        // we need to use the runOnUiThread to display it
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                Toast.makeText(ChecklistActivity.cActivity, D.T_SENDING_EMAIL, Toast.LENGTH_LONG).show();
            }
        });
        /*TODO: emailSuccessfullySent = */EMailSender.SendEmail();
    }
}).start();

I've read somewhere I could do it with a final array like so:

final boolean[] array = new boolean[1];
// Handle Automatic E-Mail Sending in a new Thread
new Thread(new Runnable() {
    @Override
    public void run() {
        // Since we want to display a Toast from within a different Thread,
        // we need to use the runOnUiThread to display it
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                Toast.makeText(ChecklistActivity.cActivity, D.T_SENDING_EMAIL, Toast.LENGTH_LONG).show();
            }
        });
        array[0] = EMailSender.SendEmail();
    }
}).start();
emailSuccessfullySent = array[0];

But I find this rather odd. Is this the generally accepted way to set a value from within a Thread, or is there a better way to do this?


Solution

  • It requires a little more overhead, but the best way to approach this problem in Android is to use a Handler. A Handler is a structure which you can use to receive messages from multiple threads and execute code on the thread the Handler is defined in. By overriding the handleMessage(Message msg) method and defining a few constants, you can send messages from any thread and have them be handled in your UI thread.

    Code:

    public boolean variable = false;
    private class MyHandler extends Handler {
        public static final int MESSAGE_TOAST = 1;
        public static final int THREAD_RETURN = 2;
    
        public void handleMessage(Message msg){
            if(msg.what == MESSAGE_TOAST){
                Toast.makeText(msg.getData().getString("toast"), Toast.LENGTH_LONG).show();
            } else if(msg.what == THREAD_RETURN){
                variable = msg.getData().getBoolean("returnValue");
            }
        }
    }
    public MyHandler handler = new MyHandler();
    

    This would make your thread look like this:

    // Handle Automatic E-Mail Sending in a new Thread
    new Thread(new Runnable() {
        @Override
        public void run() {
            Bundle bundle = new Bundle();
            bundle.setString("toast","I want to display this message");
            Message msg = handler.obtainMessage(MyHandler.MESSAGE_TOAST);
            msg.setData(bundle);
            msg.sendToTarget();
            bundle.setBoolean("returnValue", EMailSender.SendEmail());
            msg = handler.obtainMessage(MyHandler.THREAD_RETURN);
            msg.setData(bundle);
            msg.sendToTarget();
       }
    }).start();
    

    It's a little confusing when you start using Handlers, but once you get to know them, they are easy and very powerful.