android handler 调用原理
2016-06-20 16:56
495 查看
1,调度原理
andriod提供了Handler 和 Looper 来满足线程间的通信。Handler先进先出原则。Looper类用来管理特定线程内对象之间的消息交换(MessageExchange)。1)Looper: 一个线程可以产生一个Looper对象,由它来管理此线程里的MessageQueue(消息队列)。
2)Handler: 你可以构造Handler对象来与Looper沟通,以便push新消息到MessageQueue里;或者接收Looper从Message Queue取出)所送来的消息。
3) Message Queue(消息队列):用来存放线程放入的消息。
4)线程:UIthread 通常就是main thread,而Android启动程序时会替它建立一个MessageQueue。
1.Handler创建消息
每一个消息都需要被指定的Handler处理,通过Handler创建消息便可以完成此功能。Android消息机制中引入了消息池。Handler创建消息时首先查询消息池中是否有消息存在,如果有直接从消息池中取得,如果没有则重新初始化一个消息实例。使用消息池的好处是:消息不被使用时,并不作为垃圾回收,而是放入消息池,可供下次Handler创建消息时使用。消息池提高了消息对象的复用,减少系统垃圾回收的次数。
2.Handler发送消息
UI主线程初始化第一个Handler时会通过ThreadLocal创建一个Looper,该Looper与UI主线程一一对应。使用ThreadLocal的目的是保证每一个线程只创建唯一一个Looper。之后其他Handler初始化的时候直接获取第一个Handler创建的Looper。Looper初始化的时候会创建一个消息队列MessageQueue。至此,主线程、消息循环、消息队列之间的关系是1:1:1。
Hander持有对UI主线程消息队列MessageQueue和消息循环Looper的引用,子线程可以通过Handler将消息发送到UI线程的消息队列MessageQueue中。
3.Handler处理消息
UI主线程通过Looper循环查询消息队列UI_MQ,当发现有消息存在时会将消息从消息队列中取出。首先分析消息,通过消息的参数判断该消息对应的Handler,然后将消息分发到指定的Handler进行处理。
2,调度函数
关于android中Handler的postDelayed方法和removeCallbacks方法的使用方法postDelayed的作用是延迟多少毫秒后开始运行,而removeCallbacks方法是删除指定的Runnable对象,使线程对象停止运行。
方法声明如下:
public final boolean postDelayed (Runnable r, long delayMillis) 其中参数Runnable r在Handler对象所运行的线程中执行。
实例
public class HandlerActivity extends Activity { private Button mStartBtn; private Button mRemoveBtn; private int count = 0; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.handler_test); // UI线程(即主线程) Log.e("1", Thread.currentThread().getName()); mStartBtn = (Button)findViewById(R.id.start); mStartBtn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { // 在主线程中,启动一个子线程 Thread startThread = new Thread(countRunnable); startThread.start(); // 主线程 Log.e("Thread.currentThread().getName()", Thread.currentThread().getName()+">>>>>>>>>>>>>>>>end"); } }); mRemoveBtn = (Button)findViewById(R.id.remove); mRemoveBtn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { mHandler.removeCallbacks(countRunnable); } }); } private Handler mHandler = new Handler(); Runnable countRunnable = new Runnable() { @Override public void run() { Log.e("2", Thread.currentThread().getName()); count++; Log.e("!", "count=" + count); //延迟一秒,将Runnable放到主线程中执行(因此,如果是通过postDelayed方法启动一个Runnable的话,该Runnable对象是可以更新UI的) mHandler.postDelayed(countRunnable, 1000); } }; }
相关文章推荐
- android图形系统详解六:View layer
- Android SnackBar学习
- Android Studio怎么查看程序的安全码获取SHA1值? 百度地图等开发
- android系统中与内存有关的文件及路径
- 基于Android Studio的内存泄漏检测与解决全攻略
- android之隐藏actionbar、通知栏、导航栏
- Android layer-list(3)
- Android layer-list(3)
- 一个简单的上传录音demo(上传的录音安卓、苹果都可以播放)
- Android开发储存简单数据到本地的方法
- Android开发中遇到的坑
- 1.3、Android Studio创建一个Android Library
- 1.3、Android Studio创建一个Android Library
- Android 触摸屏(TP)问题现象分析和解决方法汇总
- android setCompoundDrawables 不显示问题
- 基于Android Studio的内存泄漏检测与解决全攻略
- Android Studio的内存泄漏检测
- Android 中三种启用线程的方法
- Android Studio检测内存泄露和性能
- android switch语句报错:case expressions must be constant expressions