博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Android编程基础之消息处理机制的简单实现
阅读量:4195 次
发布时间:2019-05-26

本文共 8160 字,大约阅读时间需要 27 分钟。

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();    }}
编译运行,结果如下:

你可能感兴趣的文章
Android——利用手机端的文件存储和SQLite实现一个拍照图片管理系统
查看>>
图像调优1:清晰度相关参数MTF,SFR,MTF50,MTF50P 以及TVL的概念以及换算说明
查看>>
图像调优3: CCM参数的标定
查看>>
最长回文子串(Go,LeetCode)
查看>>
奏响春的序曲,「武汉的春天」让人泪目
查看>>
情人节集体撤档,《肥龙过江》改网播,线上首映会成为常态吗?
查看>>
“抢菜大战”背后:生鲜电商的突击大考
查看>>
骁龙865+65W闪充!realme 真我X50 Pro 5G正式全球发布
查看>>
二月手机好评排行榜公布:华为第一,小米10没上榜
查看>>
英特尔展示业界首个一体封装光学以太网交换机
查看>>
年存10W+的年轻人都是怎么攒钱的
查看>>
iPhone 11全球供应紧张:何时补货未知
查看>>
小米40W无线闪充今年商用:MIX 4首发?
查看>>
5000起步没商量!vivo NEX 3S 5G手机正式发布:骁龙865+无界瀑布屏加持
查看>>
二月1500-1999元性价比排行榜:前三都是魅族手机
查看>>
疫情下的“双11”,品牌逆势增长背后的数字化变革
查看>>
支付宝变色了!被绑架了你就眨眨眼?官方如此回应...
查看>>
罗永浩欲直播带货,京东说可以帮忙联系
查看>>
B站,正在变成下一个“公众号”?
查看>>
小米启动安心服务月 手机家电产品可免费清洁保养
查看>>