Handler 原理分析和使用(二)
在上篇 Handler 原理分析和使用(一)中,介绍了一个使用Handler的一个简单而又常见的例子,这里还有一个例子,当然和上一篇的例子截然不同,也是比较常见的,实例如下。
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.os.MessageQueue;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView; public class MainActivity extends AppCompatActivity implements View.OnClickListener{ private TextView myTextView;
private Button myButton;
private Handler myHandler;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
myHandler = new Handler();
myTextView = (TextView)this.findViewById(R.id.text_view);
myButton = (Button)this.findViewById(R.id.post);
myButton.setOnClickListener(this);
} @Override
public void onClick(View view) {
int id = view.getId();
if(id == R.id.post){
Runnable updateUI = new Runnable() {
@Override
public void run() {
myTextView.setText("I get Post Message");
}
};
//将该线程发送到主线程运行
myHandler.post(updateUI);
}
}
}
实际运行这个例子,点击Button之后,TextView文字内容会变成“I get Post Message”。为什么会是这样,我们从源码开始着手查看。
先看Handler的post(Runnable)方法(post还有几个姊妹方法,这里不再一一论述,都是殊途同归)。源码如下:
public final boolean post(Runnable r)
{
return sendMessageDelayed(getPostMessage(r), 0);
}
调用了sendMessageDelayed(...), 先看getPostMessage(r),源码如下:
private static Message getPostMessage(Runnable r) {
//获取消息池中的一个消息
Message m = Message.obtain();
//将Runnable作为消息的callback
m.callback = r;
return m;
}
在看sendMessageDelayed(Message,int)的源码:(在Handler 原理分析和使用(一)中有说明)
public final boolean sendMessageDelayed(Message msg, long delayMillis)
{
if (delayMillis < 0) {
delayMillis = 0;
}
return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);
}
public boolean sendMessageAtTime(Message msg, long uptimeMillis) {
MessageQueue queue = mQueue;
if (queue == null) {
RuntimeException e = new RuntimeException(
this + " sendMessageAtTime() called with no mQueue");
Log.w("Looper", e.getMessage(), e);
return false;
}
return enqueueMessage(queue, msg, uptimeMillis);
}
private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
//绑定Handler
msg.target = this;
if (mAsynchronous) {
msg.setAsynchronous(true);
}
//将Message推入MessageQueue
return queue.enqueueMessage(msg, uptimeMillis);
}
实际上和sendMessage(Message)一样的流程。当然了紧接着Looper.loop()。然后调用到dispatchMessage(Message) 该方法需要在此重新说明。看源码:
public void dispatchMessage(Message msg) {
if (msg.callback != null) {
//如果message的callback不为空,则
handleCallback(msg);
} else {
if (mCallback != null) {
//如果Handler的callback不为空,则
if (mCallback.handleMessage(msg)) {
return;
}
}
//处理Message
handleMessage(msg);
}
}
在进入handleCallback(Message)方法查看源码:
private static void handleCallback(Message message) {
//直接执行run方法
message.callback.run();
}
注意,此时message已经是主线程对象。因此调用run方法就是在主线程中运行。
此外还需要注意,runnable要处理的内容会在主线程中处理,因此不能够占用太多的时间,从而造成ANR。
--------------------------------------------------------------------------------------------
之所以用一条线隔开,是因为还有一个实例需要说明。请注意dispatchMessage(message)里面的这段代码:
if (mCallback != null) {
//如果Handler的callback不为空,则
if (mCallback.handleMessage(msg)) {
return;
}
}
这个mCallback是从哪里来,这个有引出Handler的另一个使用方法。
首先来看Handler的初始化方法,有一下几个:
1. publicHandler()
2. publicHandler(Callback)
3. publicHandler(Looper)
4. publicHandler(Looper, Callback)
第1,3个一眼看去就明白。第4个只要明白第2个也就通了。
关键点,Callback是什么?是一个接口。源码如下:
public interface Callback {
public boolean handleMessage(Message msg);
}
该接口实际上是要求实现handleMessage(Message)方法,相信这个方法大家都不陌生。
再看该初始化方法:
Handler handler = new Handler(new Handler.Callback() {
@Override
public boolean handleMessage(Message msg) {
return false;
}
});
这里已经很明显了。就是重新定义了handleMessage方法。那么在dispatchMessage方法中如果发现mCallback不为空,则所有的消息都执行该Callback定义的handleMessage(Message).
具体的例子不想写了。今天就到这里吧。太累了。明天不在深入,而是扩展。
Handler 原理分析和使用(二)的更多相关文章
- Handler 原理分析和使用(一)
我为什么写Handler,原因主要还在于它在整个 Android 应用层面非常之关键,他是线程间相互通信的主要手段.最为常用的是其他线程通过Handler向主线程发送消息,更新主线程UI. 下面是一个 ...
- Handler 原理分析和使用之HandlerThread
前面已经提到过Handler的原理以及Handler的三种用法.这里做一个非常简单的一个总结: Handler 是跨线程的Message处理.负责把Message推送到MessageQueue和处理. ...
- Handler系列之原理分析
上一节我们讲解了Handler的基本使用方法,也是平时大家用到的最多的使用方式.那么本节让我们来学习一下Handler的工作原理吧!!! 我们知道Android中我们只能在ui线程(主线程)更新ui信 ...
- [转]Handler MessageQueue Looper消息循环原理分析
Handler MessageQueue Looper消息循环原理分析 Handler概述 Handler在Android开发中非常重要,最常见的使用场景就是在子线程需要更新UI,用Handler ...
- Mybatis插件原理分析(二)
在上一篇中Mybatis插件原理分析(一)中我们主要介绍了一下Mybatis插件相关的几个类的源码,并对源码进行了一些解释,接下来我们通过一个简单的插件实现来对Mybatis插件的运行流程进行分析. ...
- Mybatis接口编程原理分析(二)
在上一篇博客中 Mybatis接口编程原理分析(一)中我们介绍了MapperProxyFactory和MapperProxy,接下来我们要介绍的是MapperMethod MapperMethod:它 ...
- Faster RCNN原理分析(二):Region Proposal Networks详解
Faster RCNN原理分析(二):Region Proposal Networks详解 http://lib.csdn.net/article/deeplearning/61641 0814: A ...
- java基础进阶二:HashMap实现原理分析
HashMap实现原理分析 1. HashMap的数据结构 数据结构中有数组和链表来实现对数据的存储,但这两者基本上是两个极端. 数组 数组存储区间是连续的,占用内存严重,故空间复杂的很大.但数组的二 ...
- Android 4.4 KitKat NotificationManagerService使用具体解释与原理分析(二)__原理分析
前置文章: <Android 4.4 KitKat NotificationManagerService使用具体解释与原理分析(一)__使用具体解释> 转载请务必注明出处:http://b ...
随机推荐
- 学以致用:让visualstudio爱上sublime
前言: 经常在vs中工作,但是一些编辑工作却非常喜欢sublime的方式,如果你也是,那我们来当媒婆吧,哈哈. 准备: Visualstudio一枚 Sublime一枚 ...
- 如何修复在Microsoft Azure中“虚拟机防火墙打开,关闭RDP的连接端口”问题
注:下列步骤并不一定适用所有场景,提供思路,请灵活应用 我们在使用Microsoft Azure 中Windows 虚拟机,有时会发生错误打开防火墙或一些管家软件错误的关闭了"远程桌面 ...
- 使用 Puppet 在 Windows Azure 中配备 Linux 和 Windows 环境
发布于 2013-12-11 作者 Ross Gardler 微软开放技术有限公司 (MS Open Tech) 很高兴地宣布发行新的 Windows Azure Puppet 模块.通过这个模 ...
- Java I/O学习(一)
写作目的 自学Java,Java中流的概念比较复杂,故专门作一整理.期望开始学习的童鞋,看完本文后对Java流有一个大致的认识.主要分三个小篇: 一.概述.输入/输出字节流 二.输入/输出字符流.装饰 ...
- 新建应用母版页的网页index.aspx,about.aspx,login.aspx
转:http://www.netfoucs.com/liu_111111/article/details/8433491 -----------index.aspx:----------------- ...
- C# Protect the Password inside a TextBox ZZ
If the Text property is called, it will send an WM_GETTEXT message, so it will surely be an internal ...
- Bzoj 1901: Zju2112 Dynamic Rankings 树套树,线段树,平衡树,Treap
1901: Zju2112 Dynamic Rankings Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 6471 Solved: 2697[Su ...
- [Yii][RBAC]Yii中应用RBAC完全指南
开端筹办 Yii供给了强大的设备机制和很多现成的类库.在Yii中应用RBAC是很简单的,完全不须要再写RBAC代码.所以筹办工作就是,打开编辑器,跟我来. 设置参数.建树数据库 在设备数组中,增长以下 ...
- Bash For Loop Examples
How do I use bash for loop to repeat certain task under Linux / UNIX operating system? How do I set ...
- mysql left( right ) join 使用on 与where的差异
之前一直很困扰为什么left join要么一查没有数据,要么出现很多条重复数据. 百思不得其解,后来在网上到处找资料,总算明白了. 一定要理解下面几点: (1)主表条件在on后面时附表只取满足主表筛 ...