Android Handler实现子线程与子线程、主线程之间通信
一、子线程向主线程传值:
首选在主线程里创建一个Handler
1 Handler mHandler = new Handler(){
2 @Override
3 public void handleMessage(Message msg) {
4 super.handleMessage(msg);
5 switch (msg.what) {
6 case 0:
7 //do something,refresh UI;
8 break;
9 default:
10 break;
11 }
12 }
13 };
- 然后开启一个子线程,在子线程里直接使用Handler发送消息即可
1 new Thread() {
2 public void run() {
3 Message message = new Message();
4 message.obj = "子线程发送的消息Hi~Hi";
5 mHandler .sendMessage(message);
6 };
7 }.start();
- 二、主线程向子线程里发送消息:
主线程向子线程发送消息的话,我们需要在子线程里初始化Looper,并在主线程里创建的Handler引用子线程的Looper(Handler中引用的是哪个线程的Looper,就在哪个线程里处理消息)
1 public class ThreadHandlerActivity extends Activity{
2 //创建子线程
3 class MyThread extends Thread{
4 private Looper looper;//取出该子线程的Looper
5 public void run() {
6
7 Looper.prepare();//创建该子线程的Looper
8 looper = Looper.myLooper();//取出该子线程的Looper
9 Looper.loop();//只要调用了该方法才能不断循环取出消息
10 }
11 }
12
13 private Handler mHandler;//将mHandler指定轮询的Looper
14
15 protected void onCreate(Bundle savedInstanceState) {
16 super.onCreate(savedInstanceState);
17 setContentView(R.layout.main);
18 thread = new MyThread();
19 thread.start();//千万别忘记开启这个线程
20 //下面是主线程发送消息
21 mHandler = new Handler(thread.looper){
22 public void handleMessage(android.os.Message msg) {
23 Log.d("当前子线程是----->",Thread.currentThread()+"");
24 };
25 };
26 mHandler.sendEmptyMessage(1);
27 }
28
29 }
其实这样就可以达到主线程向子线程发送消息了,然而当我们运行后发现程序会Crash掉,报了一个空指针,这是因为在Handler初始化的时候,thread.looper还没有初始化,所以会报空指针,这时我们可以让主线程等待一下子线程,也可以来一个while循环来判断thread.looper是否初始化完成。不过Android本身还提供了一个方法,那就是HandlerThread:
1 protected void onCreate(Bundle savedInstanceState) {
2 super.onCreate(savedInstanceState);
3 tv = new TextView(this);
4 tv.setText("Handler实验");
5 setContentView(tv);
6
7 //实例化一个特殊的线程HandlerThread,必须给其指定一个名字
8 HandlerThread thread = new HandlerThread("handler thread");
9 thread.start();//千万不要忘记开启这个线程
10 //将mHandler与thread相关联
11 mHandler = new Handler(thread.getLooper()){
12 public void handleMessage(android.os.Message msg) {
13 Log.d("当前子线程是----->", Thread.currentThread()+"");
14 };
15 };
16 mHandler.sendEmptyMessage(1);//发送消息
17 }
这时HandlerMessage所在的线程就是HandlerThread 的子线程。
然而HandlerThread 所创建处理的子线程里是不能重写Run()方法的,你写了以后,会发现,HandlerMessage不执行了,这时因为HandlerMessage本身实现了Run()方法,我们看一下内部实现:
1 @Override
2 public void run() {
3 mTid = Process.myTid();
4 Looper.prepare();
5 synchronized (this) {
6 mLooper = Looper.myLooper();
7 notifyAll();
8 }
9 Process.setThreadPriority(mPriority);
10 onLooperPrepared();
11 Looper.loop();
12 mTid = -1;
13 }
在源代码的第4行,进行了实例化自己的Looper,如果继续追踪源代码翻看其getLooper方法你会发现,如果一个Handler在与HandlerThread进行绑定时,发现Looper为空,Handler则会一直等待直到Looper被创建出来为止,然后才继续执行后续的代码。所以我们重写了HandlerThread的run方法,肯定就不会去创建Looper对象,那么绑定的Handler就会永远处于等待状态,自然而然就不会执行到HandlerMessage信息了。这也是为什么我们要使用HandlerThread这个特殊的线程,因为使用这个,我们不必关心多线程会混乱,Looper会为空等一系列问题,只要去关心我们要实现的逻辑就行了。
三、子线程和子线程之间通信:
其实子线程向子线程之间通信,其实就是在一个子线程中创建一个Handler,它的回调自然就在此子线程中,然后在另一个子线程中调用此handler来发送消息就可以了,不过记得写上Looper哦,下面看代码:
1 new Thread(new Runnable() {
2
3 @Override
4 public void run() {
5 String msg;
6 Looper.prepare();
7
8 childHandler = new Handler() {
9 @Override
10 public void handleMessage(Message msg) {
11 super.handleMessage(msg);
12
13 System.out.println("这个消息是从-->>" + msg.obj+ "过来的,在" + "btn的子线程当中" + "中执行的");
14
15 }
16
17 };
18 Looper.loop();//开始轮循
19
20 }
21 }).start();
- 其中 Looper.prepare()和Looper.loop()一定不要忘了写。
然后我们创建第二个子线程
1 new Thread(new Runnable() {
2
3 @Override
4 public void run() {
5 Looper loop = Looper.myLooper();
6 Message msg = childHandler.obtainMessage();
7 msg.obj = "btn2当中子线程";
8 childHandler.sendMessage(msg);
9 }
10 }).start();
Android Handler实现子线程与子线程、主线程之间通信的更多相关文章
- PYTHON线程知识再研习G--线程间通信Event
很多时候,线程之间会有互相通信的需要.常见的情形是次要线程为主要线程执行特定的任务,在执行过程中需要不断报告执行的进度情况.前面的条件变量同步已经涉及到了线程间的通信(threading.Condit ...
- C#中,子线程与主线程之间的通信是如何实现(转)
注: 项目中按照这个方法调试成功: 通常我们会有这种需求: 一个支持慢速设备的处理类,如网络通信.串口通信.打印等 此时经常需要将线程封装在类里面,让类支持异步处理,然后发布事件或者回调委托通知主线程 ...
- 【转】 Pro Android学习笔记(九十):了解Handler(4):Worker线程
目录(?)[-] worker线程小例子 小例子代码worker线程通过handler实现与主线程的通信 小例子代码继承Handler代码 小例子代码子线程的Runnable 文章转载只能用于非商业性 ...
- [Android学习笔记]子线程更新UI线程方法之Handler
关于此笔记 不讨论: 1.不讨论Handler实现细节 2.不讨论android线程派发细节 讨论: 子线程如何简单的使用Handler更新UI 问题: android开发时,如何在子线程更新UI? ...
- Android 使用handler实现线程间发送消息 (主线程 与 子线程之间)、(子线程 与 子线程之间)
keyword:Android 使用handler实现线程间发送消息 (主线程 与 子线程之间).(子线程 与 子线程之间) 相信大家平时都有使用到异步线程往主线程(UI线程)发送消息的情况. 本文主 ...
- android 子线程使用handle修改主线线程内容
1.子线程使用handle修改主线线程内容简单案例 1).activity_handle.xml <?xml version="1.0" encoding="utf ...
- 2017-11-29 由runnable说起Android中的子线程和主线程
1.首先纠正一个观点,就是runnable运行在子线程中是错误的观念.runnable只是创建了一个执行任务的对象,但是它本身并不会创建一个新的子线程,Runable只是给你接口让你实现工作线程的工作 ...
- 源码分析Android Handler是如何实现线程间通信的
源码分析Android Handler是如何实现线程间通信的 Handler作为Android消息通信的基础,它的使用是每一个开发者都必须掌握的.开发者从一开始就被告知必须在主线程中进行UI操作.但H ...
- Android线程间通信机制——深入理解 Looper、Handler、Message
在Android中,经常使用Handler来实现线程间通信,必然要理解Looper , Handler , Message和MessageQueue的使用和原理,下面说一下Looper , Handl ...
- OkHttp3几个简单的例子和在子线程更新UI线程的方法
okHttp用于android的http请求.据说很厉害,我们来一起尝尝鲜.但是使用okHttp也会有一些小坑,后面会讲到如何掉进坑里并爬出来. 首先需要了解一点,这里说的UI线程和主线程是一回事儿. ...
随机推荐
- echarts饼图的配置 封装组件的注意点
1==>tooltip 类似饰hover效果提示框组件.光标放上去会触发 2==>formatter // 饼图 {a}(系列名称),{b}(数据项名称),{c}(数值), {d}(百分比 ...
- 【发现一个问题】VictoriaMetrics中,所有vmstorage在中午12:00切换索引,导致所有vm-insert发生oom
请看我提的issue: https://github.com/VictoriaMetrics/VictoriaMetrics/issues/2464 bug: vm v1.70.0, all vmst ...
- 如何计算一个uint64类型的二进制值的尾部有多少个0
作者:张富春(ahfuzhang),转载时请注明作者和引用链接,谢谢! cnblogs博客 zhihu 公众号:一本正经的瞎扯 正文 这实在是一个很简单的问题,用代码可以表示如下: func Coun ...
- python中,Microsoft Visual C++ 14.0 or greater is required问题解决方案
今天在写一个小程序,安装依赖的时候发现这个问题,平时都是直接安装Visual Studio解决,但是这个安装太大了,所以解决看看怎么安装是最方便的,最容易解决的. 下面这个就是出现的问题: build ...
- nodejs的npm改为国内源和参数
npm源改为国内 此方法不需要安装cnpm也可以使用淘宝镜像,提高国内访问速度 由于 Node 的官方模块仓库网速太慢,模块仓库需要切换到阿里的源. npm config set registry h ...
- SQL 训练题目
title: SQL 训练题目 date: 2023-7-15 01:45:50 tags: - SQL 训练 一. 查询 "01" 课程比 "02" 课程成绩 ...
- 4.1 C++ STL 动态链表容器
List和SList都是C++ STL中的容器,都是基于双向链表实现的,可以存储可重复元素的特点.其中,List内部的节点结构包含两个指针一个指向前一个节点,一个指向后一个节点,而SList只有一个指 ...
- .NET Core开发实战(第6课:作用域与对象释放行为)--学习笔记(下)
06 | 作用域与对象释放行为 接下来,把服务切换为单例模式,通过工厂的方式 services.AddSingleton<IOrderService>(p => new Dispos ...
- SQL中Between And的问题
使用Between And时需要注意的事项:(1)"between and"是包括边界值的,"not between"不包括边界值.(2)"betwe ...
- Linux-数据集 TPC-H、TPC-DS的导入和使用(MySQL)
一. TPC-H 数据集 1.数据集下载 TPC-H数据集: https://github.com/gregrahn/tpch-kit 可采用gcc下载或者直接下载zip包,然后解压即可. 具体使用方 ...