Android之Handler探索
Handler背景理解:
Handler被最多的使用在了更新UI线程中,但是,这个方法具体是什么样的呢?我在这篇博文中先领着大家认识一下什么是handler以及它是怎么样使用在程序中,起着什么样的作用。
示例说明:
首先先建立两个按钮:一个是start按钮,作用是开启整个程序。另一个是终止按钮end,作用是结束整个的程序。这两个按钮的相互对比就会让大家明白Handlerd的基本的工作原理。
运行结果截图:

MainActivity.class
package com.example.testhandler; import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button; public class MainActivity extends Activity { private Button start,end; //实例化一个handler对象
private Handler handler = new Handler();
//开启一个新的线程:开启线程有两种方式,一种是使用普通的Thread方法,另一个中是使用Runnable方法
Runnable update = new Runnable() { @Override
public void run() {
System.out.println("update");
handler.postDelayed(update, 3000);
}
}; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
start = (Button)this.findViewById(R.id.btn_start);
end = (Button)this.findViewById(R.id.btn_end); start.setOnClickListener(new OnClickListener() { @Override
public void onClick(View v) {
//加入到队列中去执行
handler.post(update);
}
}); end.setOnClickListener(new OnClickListener() { @Override
public void onClick(View v) {
//将消息移除队列中去
handler.removeCallbacks(update);
}
}); } }
当点击Start按钮时的效果图如下:

当点击end按钮时的效果图如下:

注意:
Handler中的post方法并没有开启一个新的线程,他的操作是在主线程中执行的。下面咱们就来验证一下这个观点。
首先先贴一下运行截图:

等过10s之后的运行结果是:

这里只是测试一下handler的post()方法是否是在主线程中进行的。所以没有布局。
设计思路:
在主线程中输出主线程当前的ID和Name,然后使用Runnable方式新建一个线程,在这个新线程中让程序睡眠10s,将这个线程使用Handler的post()方法发送到主线程中,看是否是执行异步加载。也就是验证handler是否是异步加载方式。结论:Handler不是异步加载方式。
MainActivity:
package com.example.handlertest1; import android.os.Bundle;
import android.os.Handler;
import android.app.Activity;
import android.view.Menu; public class MainActivity extends Activity { private Handler mhandler = new Handler(); @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//将多线程发送到消息队列中
mhandler.post(r);
//不会立刻加载界面,这说明了handler并不是开辟了一个新的线程而是在主线程中进行的。
setContentView(R.layout.activity_main);
System.out.println("Activity-->"+Thread.currentThread().getId());
System.out.println("Activity-->"+Thread.currentThread().getName());
} Runnable r = new Runnable() {
public void run() {
System.out.println("Handler--->"+Thread.currentThread().getId());
System.out.println("handler--->"+Thread.currentThread().getName());
try {
Thread.sleep(10000);
} catch (Exception e) {
e.printStackTrace();
}
}
}; }
LogCat文件的输出:
在这里通过ID号很明显的看出这不是执行的是多线程加载
在上面的主线程中重新新建一个线程则实现了多线程的加载:
将上面的onCreate()中的代码替换为:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//将多线程发送到消息队列中
// mhandler.post(r);
//不会立刻加载界面,这说明了handler并不是开辟了一个新的线程而是在主线程中进行的。
setContentView(R.layout.activity_main);
//这是另外开启了一个新的线程,会发现这里输出的速率会比上次的快很多
Thread t = new Thread(r);
t.start();
System.out.println("Activity-->"+Thread.currentThread().getId());
System.out.println("Activity-->"+Thread.currentThread().getName());
}
效果截图如下:

LogCat文件中的输出结果截图为:

在这里通过ID号很明显的看出了这是执行了多线程加载。
Handler要想开辟一个新的线程需要使用HanderThread()方法。下面就是HandlerThread()的用法:
设计思路:
通过使用handler方法传输数据,然后使用HandlerThread,实现了使用Looper来处理消息队列的功能。输出当前的Activity的ID和Name,以及Handler的ID和Name以及传输的数据
代码如下:
package com.example.handlertest1; import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Looper;
import android.os.Message; public class HandlerTest2 extends Activity{ @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); //打印当前线程的ID和当前线程的名字
System.out.println("Activity-->"+Thread.currentThread().getId());
System.out.println("Activity-->"+Thread.currentThread().getName()); //HandlerThread是以键值对的形式进行存储的,这里的handler_thread就是该handler的键名
//生成一个HandlerThread对象,实现了使用Looper来处理消息队列的功能。这是有android来提供的并不是java中的Thread提供
HandlerThread handlerthread = new HandlerThread("handler_thread");
handlerthread.start();
MyHandler myhandler = new MyHandler(handlerthread.getLooper());
Message msg = myhandler.obtainMessage();
//传送多的数据的时候使用的setData()方法,使用Bundle()将数据包装
Bundle b = new Bundle();
b.putInt("age", 20);
b.putString("name", "张三");
msg.setData(b);
//将消息发送给目标,目标就是生成该msg对象的handler
msg.sendToTarget(); } class MyHandler extends Handler{ public MyHandler(){ }
public MyHandler(Looper looper){
super(looper);
} @Override
public void handleMessage(Message msg) {
Bundle b = msg.getData();
int age = b.getInt("age");
String name = b.getString("name");
System.out.println("age is"+age+",name"+name);
System.out.println("Handler--->"+Thread.currentThread().getId());
System.out.println("Handler--->"+Thread.currentThread().getName());
System.out.println("handlermessage");
} } }
好了,就这么多了,具体的关于Handler、Looper、Message三者的关系,参考http://blog.csdn.net/lmj623565791/article/details/38377229个人感觉不错
Android之Handler探索的更多相关文章
- 《Android开发艺术探索》读书笔记 (13) 第13章 综合技术、第14章 JNI和NDK编程、第15章 Android性能优化
第13章 综合技术 13.1 使用CrashHandler来获取应用的Crash信息 (1)应用发生Crash在所难免,但是如何采集crash信息以供后续开发处理这类问题呢?利用Thread类的set ...
- 《android开发艺术探索》读书笔记(十一)--Android的线程和线程池
接上篇<android开发艺术探索>读书笔记(十)--Android的消息机制 No1: 在Android中可以扮演线程角色的有很多,比如AsyncTask.IntentService.H ...
- 《android开发艺术探索》读书笔记(十)--Android的消息机制
接上篇<android开发艺术探索>读书笔记(九)--四大组件 No1: 消息队列MessageQueue的内部存储结构并不是真正的队列,而是采用单链表的数据结构来存储消息列表,因为单链表 ...
- 《android开发艺术探索》读书笔记(八)--WindowManager
接上篇<android开发艺术探索>读书笔记(七)--动画 No1: Window是一个抽象类,它的具体实现是PhoneWindow.创建一个Window是很简单的事,只需要通过Windo ...
- 《android开发艺术探索》读书笔记(四)--View工作原理
接上篇<android开发艺术探索>读书笔记(三) No1: View的三大流程:测量流程.布局流程.绘制流程 No2: ViewRoot对应于ViewRootImpl类,它是连接Wind ...
- Android开发艺术探索第五章——理解RemoteViews
Android开发艺术探索第五章--理解RemoteViews 这门课的重心在于RemoteViews,RemoteViews可以理解为一种远程的View,其实他和远程的Service是一样的,Rem ...
- Android艺术开发探索第四章——View的工作原理(下)
Android艺术开发探索第四章--View的工作原理(下) 我们上篇BB了这么多,这篇就多多少少要来点实战了,上篇主席叫我多点自己的理解,那我就多点真诚,少点套路了,老司机,开车吧! 我们这一篇就扯 ...
- Android艺术开发探索第三章——View的事件体系(上)
Android艺术开发探索第三章----View的事件体系(上) 我们继续来看这本书,因为有点长,所以又分了上下,你在本片中将学习到 View基础知识 什么是View View的位置参数 Motion ...
- Android艺术开发探索——第二章:IPC机制(下)
Android艺术开发探索--第二章:IPC机制(下) 我们继续来讲IPC机制,在本篇中你将会学习到 ContentProvider Socket Binder连接池 一.使用ContentProvi ...
随机推荐
- 2016-3-25突然推送大量消息的问题及查找 -- Sangit
起因:2016年3月25日 18:30 左右,突然接到客户投诉,说APP收到大量的任务推送消息,而且点击进去都是一些过期任务,我们将对此展开追踪,查找问题原因. 过程: 1.当时的第一反应是先查看re ...
- 【SPOJ】Transposing is even more fun!
题意: 给出a.b 表示按先行后列的方式储存矩阵 现在要将其转置 可以交换两个点的位置 求最小操作次数 题解: 储存可以将其视为拉成一条链 设a=5.b=2 则在链上坐标用2^***(a,b)表示为( ...
- Centos6.4 coll linux 10.2
由于oracle10g太老了,只怪他娘Oracle生它生的太早了,差点就没赶上新时代(这家伙内心可也有些挺自豪的东东的,人家很有可能跟着它的主要干爹工程师为雅典奥运贡献了门票哩,生逢盛会啊!),较Ce ...
- HDU 5775 Bubble Sort (线段树)
Bubble Sort 题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5775 Description P is a permutation of t ...
- 咏南CS多层插件式开发框架支持最新的DELPHI XE7
DATASNAP中间件: 中间件已经在好几个实际项目中应用,长时间运行异常稳定,可无人值守: 可编译环境:DELPHI XE5~DELPHI XE7,无需变动代码: 支持传统TCP/IP方式也支持RE ...
- wordpress后台打开慢/卡顿的解决方法
---------------------2014年12月29日更新--------------------- 我已经用下面提到的第三种方法禁用了谷歌字体了,最近wordpress后台还是莫名奇妙地非 ...
- MongoDB的安装配置
1,下载: http://www.mongodb.org/downloads 2.4.5版:http://www.mongodb.org/dr/fastdl.mongodb.org/linux/mon ...
- 基于OpenCV的iOS开发笔记(1)
本系列文章采用的的开发环境为: 1)Xcode 6 2)OpenCV for iOS 3.0.0 -------------------分割线---------------------------- ...
- PHP 中运用 elasticsearch
PHP扩展安装 1. 环境要求:PHP_VERSION >= 5.3.9,composer工具 2. 在E盘新建文件夹命名为elastic,,拷贝composer.phar到 E:/e ...
- VS~单步调试DLL
有时我们从第三方下载DLL库之后,在使用VS进行调试时还是很麻烦的,现在我总结一下,在开发过过程中调试DLL的方法,希望对各位在开发中有帮助. 1 VS下载插件.Net Refector 2 引用你的 ...