Friday, June 5, 2015

Android example: bi-direction passing data between UI and background thread using Handler/Message.

Last example show how to use Thread, Handler and Looper in Android. In that example, UI thread pass data to background thread using Handler/Message, background thread update UI (TextView) via runOnUiThread(). It's modified in this example, background thread update UI via Handler/Message also.



In main activity, implement a custom Handler (UiHandler) and instantiate a object, then pass it to background thread via constructor.

com.example.androidthreadlooperhandler.MainActivity.java
package com.example.androidthreadlooperhandler;

import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.support.v7.app.ActionBarActivity;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;

public class MainActivity extends ActionBarActivity {

    static final int UIMSG3 = 3;
    static final int UIMSG4 = 4;

    public UiHandler uiHandler;

    Button btn1, btn2;
    TextView textInfo;

    MyThread myThread;

    private class UiHandler extends Handler{
        @Override
        public void handleMessage(Message msg) {
            // ...Run in UI Thread
            int what = msg.what;
            switch (what){
                case UIMSG3:
                    textInfo.setText("UI Message 3");
                    break;
                case UIMSG4:
                    textInfo.setText("UI Message 4");
                    break;
            }
        }
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        btn1 = (Button)findViewById(R.id.button1);
        btn2 = (Button)findViewById(R.id.button2);
        textInfo = (TextView)findViewById(R.id.info);

        btn1.setOnClickListener(btnOnClickListener);
        btn2.setOnClickListener(btnOnClickListener);

        uiHandler = new UiHandler();
        myThread = new MyThread(uiHandler);
        myThread.start();
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();

        //stop and quit the background Thread
        myThread.handler.getLooper().quit();
    }

    View.OnClickListener btnOnClickListener =
        new View.OnClickListener(){

            @Override
            public void onClick(View v) {
                if(myThread.handler != null){
                    Message message;
                    if(v==btn1){
                        message = myThread.handler.obtainMessage(MyThread.MSG1);
                    }else{
                        message = myThread.handler.obtainMessage(MyThread.MSG2);
                    }
                    myThread.handler.sendMessage(message);
                }
            }
        };

    private class MyThread extends Thread{

        static final int MSG1 = 1;
        static final int MSG2 = 2;

        public Handler handler;
        private UiHandler callbackHandler;

        MyThread(UiHandler handler){
            callbackHandler = handler;
        }

        public void run(){
            Looper.prepare();
            handler = new MyHandler();
            Looper.loop();
        }

        private class MyHandler extends Handler{
            @Override
            public void handleMessage(Message msg) {
                // ...Run in background

                int what = msg.what;
                switch (what){
                    case MSG1:

                        //doing something...
                        try {
                            Thread.sleep(2000);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }

                        Message callbackMessage3;
                        callbackMessage3 = callbackHandler.obtainMessage(UIMSG3);
                        callbackHandler.sendMessage(callbackMessage3);

                        /*
                        runOnUiThread(new Runnable() {
                            @Override
                            public void run() {
                                textInfo.setText("Message 1");
                            }
                        });
                        */

                        break;
                    case MSG2:

                        //doing something...
                        try {
                            Thread.sleep(2000);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }

                        Message callbackMessage4;
                        callbackMessage4 = callbackHandler.obtainMessage(UIMSG4);
                        callbackHandler.sendMessage(callbackMessage4);

                        /*
                        runOnUiThread(new Runnable() {
                            @Override
                            public void run() {
                                textInfo.setText("Message 2");
                            }
                        });
                        */

                        break;

                }
            }
        }
    }
}


The layout file refer to last example Thread, Handler and Looper in Android.

Next:
Android example: pass string between threads, in Bundler

No comments: