Android编程基础之消息处理机制的简单实现

来源:互联网 发布:unity3d toon shader 编辑:程序博客网 时间:2024/06/08 15:04

Android通过Looper、Handler来实现消息循环机制。Android的消息循环是针对线程的,每个线程都可以有自己的消息队列和消息循环。本文通过几个简单的例子来说明一下Android消息机制的基本使用方法。(本文所有的例子都是基于Android Studio 2.2.3)


一、自定义消息处理机制

首先定义一个子线程,实现消息队列和消息循环,这个子线程的具体实现如下:

 /* 定义一个子线程,实现消息队列和消息循环 */    class MyThread extends Thread{        private Looper looper = null;        @Override        public void run() {            super.run();            Looper.prepare();       // 创建消息队列            /* 同步代码块,获得当前线程的Looper对象 */            synchronized (this){                looper = Looper.myLooper();                notifyAll();            }            Looper.loop();          // 进入消息循环        }        public Looper getLooper(){            if (!isAlive()) {                return null;            }            // If the thread has been started, wait until the looper has been created.            synchronized (this) {                while (isAlive() && looper == null) {                    try {                        wait();                    } catch (InterruptedException e) {                        e.printStackTrace();                    }                }            }            return looper;        }    }
并在这个子线程中实现了一个public方法getLooper(),用来和具体的handler进行绑定。在主线程中添加一个按钮,每次按下按钮就向子线程发送一条消息,整个例子完整的代码如下所示:

package cn.edu.syau.yl_app_handler_msg;import android.os.Handler;import android.os.Looper;import android.os.Message;import android.support.v7.app.AppCompatActivity;import android.os.Bundle;import android.view.View;import android.widget.Button;public class MainActivity extends AppCompatActivity {    private final String KEY = "MESSAGE";    private Button button = null;    private MyThread thread = null;    private Handler handler = null;    /* 定义一个子线程,实现消息队列和消息循环 */    class MyThread extends Thread{        private Looper looper = null;        @Override        public void run() {            super.run();            Looper.prepare();       // 创建消息队列            /* 同步代码块,获得当前线程的Looper对象 */            synchronized (this){                looper = Looper.myLooper();                notifyAll();            }            Looper.loop();          // 进入消息循环        }        public Looper getLooper(){            if (!isAlive()) {                return null;            }            // If the thread has been started, wait until the looper has been created.            synchronized (this) {                while (isAlive() && looper == null) {                    try {                        wait();                    } catch (InterruptedException e) {                        e.printStackTrace();                    }                }            }            return looper;        }    }    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        button = (Button) findViewById(R.id.btnSend);        button.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                Message message = handler.obtainMessage();                Bundle bundle = new Bundle();                bundle.putString(KEY, "TECH-PRO!");                message.setData(bundle);                handler.sendMessage(message);                System.out.println("main to child : send a message!");            }        });        /* 启动子线程,进行消息循环,接收主线程发送过来的消息 */        thread = new MyThread();        thread.start();        /* 将这个handler和子线程进行绑定,处理子线程接收到的消息 */        handler = new Handler(thread.getLooper(), new Handler.Callback() {            @Override            public boolean handleMessage(Message msg) {                Bundle bundle = msg.getData();                String string = bundle.getString(KEY);                System.out.println("child from main : " + string);                return false;            }        });    }}
编译运行,结果如下:



二、实现主线程向子线程发送消息

实现和上面同样的功能,但是使用系统自带的HandlerThread类,它里面已经创建了消息队列并且实现了消息循环,使用起来简单高效,完整的测试代码如下所示:

package cn.edu.syau.yl_app_handler_msg;import android.os.Handler;import android.os.HandlerThread;import android.os.Looper;import android.os.Message;import android.support.v7.app.AppCompatActivity;import android.os.Bundle;import android.view.View;import android.widget.Button;public class MainActivity extends AppCompatActivity {    private final String KEY = "MESSAGE";    private Button button = null;    private HandlerThread handlerThread = null;    private Handler handler = null;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        button = (Button) findViewById(R.id.btnSend);        button.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                Message message = handler.obtainMessage();                Bundle bundle = new Bundle();                bundle.putString(KEY, "TECH-PRO!");                message.setData(bundle);                handler.sendMessage(message);                System.out.println("main to child : send a message!");            }        });        /* 启动子线程,进行消息循环,接收主线程发送过来的消息 */        handlerThread = new HandlerThread("TECH-PRO");        handlerThread.start();        /* 将这个handler和子线程进行绑定,处理子线程接收到的消息 */        handler = new Handler(handlerThread.getLooper(), new Handler.Callback() {            @Override            public boolean handleMessage(Message msg) {                Bundle bundle = msg.getData();                String string = bundle.getString(KEY);                System.out.println("child from main : " + string);                return false;            }        });    }}


编译并运行结果如下:


三、实现子线程向主线程发送消息

实现和上面例子相反的功能,因为在Android的主线程或者UI线程中已经默认创建了消息队列,并且实现了消息循环,所以只需要只需要将消息处理handler与主线程进行绑定就可以处理主线程的消息了。为了实现这个功能,还需要实现一个子线程向主线程发送消息,这个子线程的具体实现如下:

 /* 定义一个子线程用于发送消息 */    class MyThread extends Thread{        @Override        public void run() {            for(;;) {                Message message = myHandler.obtainMessage();                Bundle bundle = new Bundle();                bundle.putString(KEY, "TECh-PRO!");                message.setData(bundle);                myHandler.sendMessage(message);                try {                    Thread.sleep(3000);                } catch (InterruptedException e) {                    e.printStackTrace();                }                System.out.println("child to main : send a message!");            }        }   }


整个例子的完整代码如下所示:

package cn.edu.syau.yl_app_handler_msg;import android.os.Bundle;import android.os.Handler;import android.os.Looper;import android.os.Message;import android.support.v7.app.AppCompatActivity;public class MainActivity extends AppCompatActivity {    private final String KEY = "TECH-PRO";    private MyHandler myHandler = null;    private MyThread myThread = null;    /* 定义一个handler用来处理子线程发给主线程的消息 */    class MyHandler extends Handler{        public MyHandler(){}        public MyHandler(Looper looper){super(looper);}        @Override        public void handleMessage(Message msg) {            super.handleMessage(msg);            Bundle bundle = msg.getData();            String string = bundle.getString(KEY);            System.out.println("main from child : " + string);        }    }    /* 定义一个子线程用于发送消息 */    class MyThread extends Thread{        @Override        public void run() {            for(;;) {                Message message = myHandler.obtainMessage();                Bundle bundle = new Bundle();                bundle.putString(KEY, "TECh-PRO!");                message.setData(bundle);                myHandler.sendMessage(message);                try {                    Thread.sleep(3000);                } catch (InterruptedException e) {                    e.printStackTrace();                }                System.out.println("child to main : send a message!");            }        }    }    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        /* 将主线程和handler消息处理绑定在一起 */        myHandler = new MyHandler(MainActivity.this.getMainLooper());        myThread = new MyThread();        myThread.start();    }}
编译运行,结果如下:



原创粉丝点击