Android笔记(三十) Android中线程之间的通信(二)Handler消息传递机制
什么是Handler
之前说过了,Android不允许主线程(MainThread)外的线程(WorkerThread)去修改UI组件,但是又不能把所有的更新UI的操作都放在主线程中去(会造成ANR),那么只能单独启动一个子线程(WorkerThread)去处理,处理完成之后,将结果通知给UI主线程,子线程和主线程的通信就用到了Handler。
Handler、Looper和MessageQueue的基本原理
先看一下他们的职责:
Handler——处理者,负责发送以及处理Message。
MessageQueue——消息队列,用来存放Handler发送过来的消息,采用FIFO(first in first out)规则将Message以链表的方式串联起来的,等待Looper的抽取。
Looper——消息泵,不断的从消息队列中取出消息并回传给Handler

1. Handler对象调用obtainMessage()方法获取Message对象
2. 调用sendMessage(Message msg)方法将消息发送到消息队列(MessageQueue)中
3. Looper循环这从消息队列中取出msg
4. 调用Handler对象的handleMessage(Message msg)方法,将取出的msg传给Handler
Handler将消息传到队列,Looper从队列中拿到消息,然后又传给了Handler,这似乎是一个无用功,我们通过代码来看一下。
package cn.lixyz.handlertest; import android.app.Activity;
import android.graphics.drawable.BitmapDrawable;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView; /**
* 实现点击按钮,开始播放幻灯片,每张幻灯片间隔2s。
*/ public class MainActivity extends Activity { private Button button;
private Handler handler; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); button = (Button) findViewById(R.id.button); handler = new MyHandler(); button.setOnClickListener(new ButtonOnClickListener()); } class ButtonOnClickListener implements View.OnClickListener { @Override
public void onClick(View v) {
Thread t = new ChangePicThread();
t.start();
}
} class ChangePicThread extends Thread {
@Override
public void run() {
super.run();
try {
Thread.sleep(1 * 1000);
Log.d("TTTTT", "---->" + Thread.currentThread().getName());
Message msg = handler.obtainMessage();
msg.what = 100;
handler.sendMessage(msg);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
} //创建内部类,继承Handler,用来创建Handle对象
class MyHandler extends Handler {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
Log.d("TTTTT", "====>" + Thread.currentThread().getName());
int i = msg.what;
Log.d("TTTTT", "message=" + i);
}
}
}
MainActivity.java
<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:orientation="vertical"
tools:context=".MainActivity"> <Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginTop="30dp"
android:text="sendMessage" /> </LinearLayout>
activity_main.xml
点击按钮,查看log
09-16 10:55:12.064 12614-12669/cn.lixyz.handlertest D/TTTTT﹕ ---->Thread-213
09-16 10:55:12.064 12614-12614/cn.lixyz.handlertest D/TTTTT﹕ ====>main
09-16 10:55:12.064 12614-12614/cn.lixyz.handlertest D/TTTTT﹕ message=100
可以看到,ChangePicThread的线程名是Thread-213,MyHandler的线程名是main,那message也传递过来了,那我们不就可以在线程中将所需要处理的内容处理好,将结果传给Handler,由Handler去修改UI么
一个简单的Handler例子
点击按钮,开始播放幻灯片。
package cn.lixyz.handlertest; import android.app.Activity;
import android.graphics.drawable.BitmapDrawable;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView; /**
* 实现点击按钮,开始播放幻灯片,每张幻灯片间隔2s。
*/ public class MainActivity extends Activity { private ImageView imageView;
private Button button;
private Handler handler;
private int[] images = {R.drawable.pic1,
R.drawable.pic2, R.drawable.pic3, R.drawable.pic4, R.drawable.pic5, R.drawable.pic6,};
private int index = 0; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); button = (Button) findViewById(R.id.button);
imageView = (ImageView) findViewById(R.id.imageView); handler = new MyHandler(); button.setOnClickListener(new ButtonOnClickListener()); } //创建内部类,实现OnClickListener接口,用于注册监听按钮开始事件
class ButtonOnClickListener implements View.OnClickListener { @Override
public void onClick(View v) {
Thread t = new ChangePicThread();
t.start();
}
} //创建内部类,用户执行2s变换幻灯片
class ChangePicThread extends Thread {
@Override
public void run() {
super.run();
try { while (true) {
Object obj = new Object();
synchronized (obj) {
Message msg = handler.obtainMessage();
msg.obj = index;
handler.sendMessage(msg);
index++;
Thread.sleep(2 * 1000);
if (index >= images.length ) {
index = 0;
}
}
} } catch (InterruptedException e) {
e.printStackTrace();
}
}
} //
class MyHandler extends Handler {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
int i = (int) msg.obj;
BitmapDrawable bd = (BitmapDrawable) imageView.getDrawable();
if (bd != null && !bd.getBitmap().isRecycled()) {
bd.getBitmap().recycle();
}
imageView.setImageResource(images[i]);
}
}
}
MainActivity.java
<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:orientation="vertical"
tools:context=".MainActivity"> <ImageView
android:id="@+id/imageView"
android:layout_width="match_parent"
android:layout_height="wrap_content" /> <Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginTop="30dp"
android:text="点击播放" /> </LinearLayout>
activity_main.xml
Android笔记(三十) Android中线程之间的通信(二)Handler消息传递机制的更多相关文章
- Android笔记(三十一)Android中线程之间的通信(三)子线程给主线程发送消息
先看简单示例:点击按钮,2s之后,TextView改变内容. package cn.lixyz.handlertest; import android.app.Activity; import and ...
- Android笔记(三十四) Android中线程之间的通信(六)Handle中的post()方法详解
我们之前都是使用sendMessage()方法来发送消息,使用handleMessage来处理消息的,今天我们来看另外一种方法,先看代码: package cn.lixyz.handlertest; ...
- Android笔记(三十二) Android中线程之间的通信(四)主线程给子线程发送消息
之前的例子都是我们在子线程(WorkerThread)当中处理并发送消息,然后在主线程(UI线程)中获取消息并修改UI,那么可以不可以在由主线程发送消息,子线程接收呢?我们按照之前的思路写一下代码: ...
- Android笔记(三十三) Android中线程之间的通信(五)Thread、Handle、Looper和MessageQueue
ThreadLocal 往下看之前,需要了解一下Java的ThreadLocal类,可参考博文: 解密ThreadLocal Looper.Handler和MessageQueue 我们分析一下之前的 ...
- Android笔记三十四.Service综合实例二
综合实例2:client訪问远程Service服务 实现:通过一个button来获取远程Service的状态,并显示在两个文本框中. 思路:如果A应用须要与B应用进行通信,调用B应用中的getName ...
- Java多线程中线程间的通信
一.使用while方式来实现线程之间的通信 package com.ietree.multithread.sync; import java.util.ArrayList; import java.u ...
- java线程之间的通信
1.常用的方法 sleep() 该线程进入等待状态,不释放锁 wait() 该线程进入等待状态,释放锁 notify() 随机唤醒一个线程 notifyAll() 唤醒全部线程 getName() 获 ...
- Android系列之Fragment(三)----Fragment和Activity之间的通信(含接口回调)
[声明] 欢迎转载,但请保留文章原始出处→_→ 生命壹号:http://www.cnblogs.com/smyhvae/ 文章来源:http://www.cnblogs.com/smyhvae/p/ ...
- Java学习笔记46(多线程三:线程之间的通信)
多个线程在处理同一个资源,但是线程的任务却不相同,通过一定的手段使各个线程能有效地利用资源, 这种手段即:等待唤醒机制,又称作线程之间的通信 涉及到的方法:wait(),notify() 示例: 两个 ...
随机推荐
- Ideal 使用帮助手册
1.设置Ideal启动时选择工作空间 将Reopen last project on starup 取消勾选
- 用漫画的形式来讲解为什么MySQL数据库要用B+树存储索引?
小史是一个应届生,虽然学的是电子专业,但是自己业余时间看了很多互联网与编程方面的书,一心想进BAT互联网公司. 话说两个多月前,小史通过了A厂的一面,两个多月后的今天,小史终于等到了A厂的二面. 简单 ...
- pipline中替换tag变量
实验架构: 192.168.0.96 gitlab 192.168.0.97 jenkins 192.168.0.98 harbor.docker集群 说明:下面代码编译镜像那一步的代码必须靠左,目的 ...
- xray写POC踩坑
错误记录 静态文件目录不一定是static. 只考虑了linux的情况,如果是 windows 呢,能读取某些应用自己的源码吗. 实际环境参数不一定是id,thinkphp 不适合使用 poc 来写 ...
- Appium移动自动化测试-----(二)安装 Android SDK
安装Android SDK Android SDK(Software Development Kit,软件开发工具包)提供了 Android API 库和开发工具构建,测试和调试应用程序.简单来讲,A ...
- Qt qml的软件架构设计
google: qt qml application architecture 有很多资源. 1 https://www.ics.com/blog/multilayered-architecture- ...
- [VS] - 手工打开 WCF 客户端调试工具
操作步骤 1. 在开始菜单中找到 Visual Studio 命令行工具 2. 输入命令 wcftestclient 即可打开 WCF 客户端测试工具 参考资料http://www.cnblogs.c ...
- (一)SpringBoot Demo之 Hello World
文章目录 最终效果 pom文件编写 编写资源类 编写控制器 运行项目 原文 : https://spring.io/guides/gs/rest-service/ 类型:官网入门指南 要求:JDK1. ...
- 下载安装Git,学习笔记
官方地址为:https://git-scm.com/download/win 2.下载完之后,双击安装,全部选择默认. 3.选择安装目录 4.选择组件 5.开始菜单目录名设置 6.选择使用命令行环境 ...
- Python 数据结构理解分享
摘要:分享学习Python数据结构的一些理解,主要包含序列(如列表和元组),映射(如字典)以及集合3中基本的数据结构,以及可变和不可变数据类型. Python 中的数据结构是根据某种方式将数据元素组合 ...