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 ...
随机推荐
- C语言程序设计第10堂作业
一.本次课主要内容: 本次课程学习数组,一种最基本的构造类型,它是一组相同类型数据的有序集合.数组中的元素在内存中连续存放,每个元素都属于同一种数据类型,用数组名和下标可以唯一地确定数组元素: (1) ...
- C#中的接口实现多态
我们都知道虚方法实现多态,抽象方法实现多态等,我们今天来看看如何使用接口实现多态 1.首先我们先要来了解了解什么是接口,它存在的意识 01.接口就是为了约束方法的格式(参数和返回值类型)而存在的 02 ...
- [Jquery] 获取地址栏参数的方法 备忘
<script type="text/javascript"> (function ($) { $.getUrlParam = function (name) { va ...
- SQLite使用教程11 表达式
SQLite 表达式 表达式是一个或多个值.运算符和计算值的SQL函数的组合. SQL 表达式与公式类似,都写在查询语言中.您还可以使用特定的数据集来查询数据库. 语法 假设 SELECT 语句的基本 ...
- ubuntu中使用nginx把本地80端口转到其他端口
ubuntu中使用nginx把本地80端口转到其他端口 因为只是在开发的过程中遇到要使用域名的方式访问, 而linux默认把1024以下的端口全部禁用. 在网上找了N多方式开启80端口无果后, 方才想 ...
- 有关autoresizingMask属性遇到的一个小问题
前言:在讲述这个小问题之前,我们有必要先了解一下UIViewAutoresizing的有关属性概念和使用详解. 参考:自动布局之autoresizingMask使用详解(Storyboard& ...
- 实现AT24C02的数据读写操作
/*************************************************************** 功能:11:32 2008-6-27 作者:SG 时间:2004-03 ...
- Android仿人人客户端(v5.7.1)——个人主页(三)
转载请标明出处:http://blog.csdn.net/android_ls/article/details/9405089 声明:仿人人项目,所用所有图片资源都来源于其它Android移动应用,编 ...
- QUIC协议的分析,性能测试以及在QQ会员实践
WeTest 导读 你听过HTTPS.HTTP2.0.SPDY,但是这些应用层协议都是基于可靠的传输层协议TCP来实现的.那么,基于高效的UDP协议有没有一种相对可靠的应用层协议呢? Why QUIC ...
- day12(表达式,推导式,名称空间与作用域,函数的嵌套定义)
一,复习 # 字符串的比较 # -- 按照从左往右比较每一个字符,通过字符对应的ascll进行比较 # print('a' > 'A') #True # print('ac' > 'ab' ...