Friday, May 29, 2015

Android example: Thread, Handler and Looper

Example to run task on background thread using Thread, Handler and Looper:


com.example.androidthreadlooperhandler.MainActivity
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 {

    Button btn1, btn2;
    TextView textInfo;

    MyThread myThread;

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

        myThread = new MyThread();
        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;

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

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

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

                        break;

                }
            }
        }
    }
}


layout/activity_main.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingLeft="10dp"
    android:paddingRight="10dp"
    android:paddingTop="10dp"
    android:paddingBottom="10dp"
    android:orientation="vertical"
    tools:context=".MainActivity">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:autoLink="web"
        android:text="http://android-er.blogspot.com/"
        android:textStyle="bold" />

    <Button
        android:id="@+id/button1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Button 1"/>

    <Button
        android:id="@+id/button2"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Button 2"/>

    <TextView
        android:id="@+id/info"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>

</LinearLayout>



In this example, background thread update UI (TextView) via runOnUiThread(). It's modified in next example to implement Handlers in both UI and background thread, to pass data in both direction via Handler/Message.


No comments: