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线程和主线程是一回事儿. ...
随机推荐
- 【分享代码片段】terraform中,如何从刚刚创建的 deployment 中获得所有容器的名字和 ip
作者:张富春(ahfuzhang),转载时请注明作者和引用链接,谢谢! cnblogs博客 zhihu Github 公众号:一本正经的瞎扯 不好意思,刚刚才开始用 terraform,或许是更好的办 ...
- centos7.9离线安装MongoDB4.4.17
前言 MongoDB 5.0开始要求CPU支持avx指令集,参考https://mp.weixin.qq.com/s/6FFXih1DEZYDFOk1hCu69w 环境 CentOS 7.9.2009 ...
- Xcode的Search Paths配置
在Xcode中的文件搜索路径配置有两个地方,一个是Project层的配置,一个是Target的配置. Project-Build Settings-Search Paths Target-Build ...
- pandas教程01: pandas的安装和基本操作
pandas是Python中常用的数据处理库,主要用来处理表格数据,类似于下面这种: 好好干文化有限公司员工薪资表 姓名 年龄 性别 年薪 奖金 久九刘 35 男 182600 42000 傅儿待 ...
- 【奶奶看了都会】ComfyUI+SVD制作AI视频教程,附效果演示
AI一天,人间一年 大家好啊,我是小卷,最近AI绘画又发展出一些新玩意了,小卷因为工作的关系有一个月没关注AI的发展了,都有点跟不上版本节奏了... 1.comfyui的使用效果 今天给大家介绍下AI ...
- Mac 上 snail svn 配置验证信息
这样就不用每次都得输入svn的账号 和 密码了
- Java发送mail和C#发送mail
Java发送mail 阿里云邮箱,配置公司邮箱服务器,邮箱地址,授权码(运维同事提供,听说阿里云邮箱的授权码和密码一样),端口465,测试能发送. /** * 发送简单的文本邮件 */ public ...
- [Spring]Junit单元测试时取不到本地文件问题
Junit单元测试时取不到本地文件问题 问题 当使用Junit进行单元测试时,遇到了以下问题: 2022-10-24 16:13:19.902 [main] ERROR zonetop.gisboot ...
- NC24953 [USACO 2008 Jan G]Cell Phone Network
题目链接 题目 题目描述 Farmer John has decided to give each of his cows a cell phone in hopes to encourage the ...
- Goland 使用[临时]
环境变量 因为module模式的引入, 多个项目可以共用同一套External Libraries, 在File->Settings->Go中, 设置GOROOT为go安装目录, 例如 / ...