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 ...
随机推荐
- POJ_2392_Space_Elevator_(动态规划,背包)
描述 http://poj.org/problem?id=2392 磊方块,每种方块有数量,高度,以及该种方块所能处在的最高高度.问最高磊多高? Space Elevator Time Limit: ...
- 剧烈变化的移动互联网O2O
- php 正则校验是否是域名
/** * @description 匹配 * t.cn 正确 * t-.cn 错误 * tt.cn正确 * -t.cn 错误 * t-t.cn 正确 * tst-test-tst.cn 正确 * t ...
- uploadify上传图片(限制最多五张)
项目中遇到图片上传的情况,好多都是使用服务器上传控件进行上传的,很是不爽. 然后在网上找到了uploadify的方法,自己总结和修改后分享给大家. 项目文档预览: 1.引用原有css和js &l ...
- JSP页面同时操作所有Input输入框
项目里要写个function,对页面上所有input输入框进行非空判断,对非空input全部置为readOnly,提交的时候判断是否有空白项目. var inputs=document.getElem ...
- chapter3:Collaborative Filtering ---------A Programmer's Guide to Data Mining
Implicit rating and item based filtering Explicit rating: 用户明确的对item评分 Implicit rating:反之 明确评分所存在的问题 ...
- Jsp_demo:自定义标签
Jsp自定义标签: 1.继承SimpleTagSupport,重写doTag(). 2.在WEB-INF/ 下配置**.tld文件 3.Jsp页面引入自定义标签:<%@ taglib uri=& ...
- Tornado源码探寻(准备阶段)
上一篇从一个简单的例子大致了解到Tornado框架的一个概述,同时也看清了web框架的本质. 接下来,我们从tornado程序的起始来分析其源码: 一.概述 上图是摘自朋友的博客里的内容,这张图很明确 ...
- 开源软件授权协议详解(GPL/MPL/LGPL/BSD/Apache Licence/Creative Commons/MIT)
开源在今天的软件业已经很普遍,但开源是否意味着使用者可以对开源后的代码为所欲为呢? 答案是否定的. 开源运动同样有自己的游戏规则和道德准则. 不遵行这些规则不但损害开源运动的健康发展,也会对违规者造成 ...
- 怎样在Yii中显示静态页
在web应用中,我们经产更需要显示静态页,如“关于我们”等,这些文件通常是静态页,通常有如下几种处理方法: 1.把独立的html文件存在Web服务器能直接访问的目录下.这种方案的缺点是很难维护网页布局 ...