Android 非UI线程中是不能更新UI的,Handler是Android 提供的一套更新UI的机制,也是用来发送消息和处理消息的一套机制。

以前刚接触的Handler的时候,感觉总是很困惑,对Handler原理也是一知半解,现在对Handler常见用法,知识点总结一下。

先看一下谷歌Android官方文档对Handler的描述:

Class Overview


A Handler allows you to send and process Message and Runnable objects associated with a thread'sMessageQueue. Each Handler instance is associated with a single thread and that thread's message queue. When you create a new Handler, it is bound to the thread / message queue of the thread that is creating it -- from that point on, it will deliver messages and runnables to that message queue and execute them as they come out of the message queue. 

它允许用户发送、处理消息和与线程的消息队列相关联的 runnable 对象。每一个 handler 实例都与一个单独的线程相关联。每次创建一个新的 hander 对象时,它都与创建该对象的线程或者该线程中的消息队列绑定在一起,这样handler 就可以发送消息和 runable 对象到消息队列中,并在从消息队列中取出的时候处理它们。


1. Handler的构造函数


  • Handler()   Default constructor associates this handler with the Looper for the current thread.
  • Handler(Handler.Callback callback) Constructor associates this handler with theLooper for the current thread and takes a callback interface in which you can handle messages.

  • Handler(Looper looper)  Use the provided Looper instead of the default one.

  • Handler(Looper looper, Handler.Callback callback)  Use the provided Looper instead of the default one and take a callback interface in which to handle messages.

 
说明:    Handler ()是最常用的一种

   Handler(Handler.Callback callback)可以截获消息,

   Handler(Looper looper)指定了Looper对象,在实际开发中常用HandlerThread.getLooper()。


2. 关于Message


Handler如果使用sendMessage的方式把消息入队到消息队列中,需要传递一个Message对象,而在Handler中,需要重 写handleMessage()方法,用于获取工作线程传递过来的消息。

发送消息常见的方式如下,用法大同小异。

  • sendEmptyMessage(int what) 发送一个空的消息
  • sendMessageAtTime(Message msg, long uptimeMillis) 在某一时间点发送一个空的消息
  • sendMessageDelayed(Message msg, long delayMillis)  延迟发送一个空的消息
  • sendMessage(Message msg)发送消息,消息中可以携带参数

Message的参数:

  • int what:定义的消息码,一般用于设定消息的标志。
  • int arg1:简单参数
  • int arg2:简单参数
  • Object obj:传递一个任意的对象。

移除Message

  • removeMessages(int what)   Remove any pending posts of messages  with code 'what' that are in the message queue.


3. 关于Post


Post 会传递一个Runnable对象到消息队列中

Post常见方法

  • post(Runnable r) Causes the Runnable r to be added to the message queue.
  • postDelayed(Runnable r, long delayMillis) Causes the Runnable r to be added to the message queue, to be run after the specified amount of time elapses.
  • postAtTime(Runnable r,Object token, long uptimeMillis) Causes the Runnable r to be added to the message queue, to be run at a specific time given byuptimeMillis.


消息队列中移除一个Runnable对象
removeCallbacks(Runnable r)Remove any pending posts of Runnable r that are in the message queue.

4. 关于MessageQueue


MessageQueue 是消息队列,在MainThread创建的时候会创建一个Looper,在创建Looper的时候,会创建MessageQueue();

5. 关于Looper


      Looper.loop()是一个死循环,用来循环查询消息队列,并把消息回传给handler。

    

6. Demo说明





1.1 发送空消息和移除消息,这里以sendEmptyMessageDelayed()为例

public class Test1 extends Activity implements OnClickListener {private TextView tv;private Button btn;private int i = 0;Handler handler = new Handler() {public void handleMessage(Message msg) {tv.setText("Hello 改变了"+i++);handler.sendEmptyMessageDelayed(0, 1 * 1000); //延迟一秒发送};};@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.test1);setView();test1();}private void setView() {tv = (TextView) this.findViewById(R.id.tv);btn = (Button) this.findViewById(R.id.btn);btn.setOnClickListener(this);}private void test1() {new Thread() {public void run() {handler.sendEmptyMessageDelayed(0, 1 * 1000); //延迟一秒发送};}.start();}@Overridepublic void onClick(View v) {switch (v.getId()) {case R.id.btn:handler.removeMessages(0);//移除消息break;default:break;}}}


效果图,数字每隔一秒,自增1,点击,数字会停止自增:



1.2 使用new Message(),并给Message赋值,使用handler.sendMessage(msg)发送

public class Test2 extends Activity implements OnClickListener {private TextView tv;Handler handler = new Handler() {public void handleMessage(Message msg) {tv.setText("msg.what=" + msg.what + ",     msg.arg1=" + msg.arg1+ ",    msg.arg2=" + msg.arg2 + ",    msg.obj=" + msg.obj);};};@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.test2);setView();test();}private void setView() {tv = (TextView) this.findViewById(R.id.tv);}private void test() {new Thread() {public void run() {Message msg = new Message();UserBean userBean = new UserBean();userBean.setName("Jim");userBean.setPwd("123456");msg.what = 1;msg.arg1 = 2;msg.arg2 = 3;msg.obj = userBean;handler.sendMessage(msg);};}.start();}@Overridepublic void onClick(View v) {switch (v.getId()) {////case R.id.btn://handler.removeMessages(0);//移除消息//break;default:break;}}}

实体类

public class UserBean {public String name;public String pwd;public String getName() {return name;}public void setName(String name) {this.name = name;}public String getPwd() {return pwd;}public void setPwd(String pwd) {this.pwd = pwd;}@Overridepublic String toString() {return "UserBean [name=" + name + ", pwd=" + pwd + "]";}}


效果图如下,可以看到消息成功传递和接收。



1.3 使用obtainMessage()获取已绑定的消息,并给Message赋值,使用msg.sendToTarget()发送

public class Test3 extends Activity implements OnClickListener {private TextView tv;Handler handler = new Handler() {public void handleMessage(Message msg) {tv.setText("msg.what=" + msg.what + ",     msg.arg1=" + msg.arg1+ ",    msg.arg2=" + msg.arg2 + ",    msg.obj=" + msg.obj);};};@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.test3);setView();test();}private void setView() {tv = (TextView) this.findViewById(R.id.tv);}private void test() {new Thread() {public void run() {// Message msg = new Message();Message msg = handler.obtainMessage();UserBean userBean = new UserBean();userBean.setName("Jim");userBean.setPwd("123456");msg.what = 1;msg.arg1 = 2;msg.arg2 = 3;msg.obj = userBean;// handler.sendMessage(msg);nmsg.sendToTarget();};}.start();}@Overridepublic void onClick(View v) {switch (v.getId()) {//// case R.id.btn:// handler.removeMessages(0);//移除消息// break;default:break;}}}


效果和上图一样

Post 会传递一个Runnable对象到消息队列中

2.1 使用Post方式传递一个Runnable对象到消息队列和移除

public class Test4 extends Activity implements OnClickListener {private TextView tv;private Button btn;private int i = 0;Handler handlerPost = new Handler();// 线程中运行该接口的run函数Runnable update_thread = new Runnable() {public void run() {// System.out.println("activity_id---->"+Thread.currentThread().getId());// System.out.println("activity_name---->"+Thread.currentThread().getName());tv.setText("handlerPost:"+i++);// 延时1s后又将线程加入到线程队列中handlerPost.postDelayed(update_thread, 1000);}};@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.test4);setView();System.out.println("activity_id0---->" + Thread.currentThread().getId());System.out.println("activity_name0---->"+ Thread.currentThread().getName());test();}private void setView() {tv = (TextView) this.findViewById(R.id.tv);btn = (Button) this.findViewById(R.id.btn);btn.setOnClickListener(this);}private void test() {// 将线程接口立刻送到线程队列中handlerPost.post(update_thread); // handler使用了post方法启动了runnbale,其实启动的线程和activity主线程是同一个线程// Thread t = new Thread(update_thread);// //这样绑定的线程与它所在的activity线程就不是同一个线程了// t.start();}@Overridepublic void onClick(View v) {switch (v.getId()) {case R.id.btn:handlerPost.removeCallbacks(update_thread);// 将接口从线程队列中移除break;default:break;}}}

说明:
handler使用了post方法启动了runnbale,其实启动的线程和activity主线程是同一个线程

如果使用

Thread t = new Thread(update_thread);

t.start();

这样绑定的线程与它所在的activity线程就不是同一个线程了

效果图:



  Handler(Looper looper)的使用,使用handThread.getLooper()作为参数。

 注意:如果 thread.getLooper()中的thread为子线程,则会报空指针异常,因为当主线程执行Handler(Looper looper)

的时候,子线程的Looper对象还未创立。


public class Test5 extends Activity implements OnClickListener {private TextView tv;HandlerThread handThread;Handler handler;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.test5);setView();test();}private void setView() {tv = (TextView) this.findViewById(R.id.tv);}private void test() {// HandlerThreadhandThread = new HandlerThread("handThread");handThread.start();handler = new Handler(handThread.getLooper()) {public void handleMessage(Message msg) {tv.setText("HandlerThread");};};handler.sendEmptyMessage(0);}@Overridepublic void onClick(View v) {switch (v.getId()) {//// case R.id.btn:// handler.removeMessages(0);//移除消息// break;default:break;}}}


效果图:



Demo下载地址:http://download.csdn.net/detail/yalinfendou/8477587

更多相关文章

  1. Android的异步加载
  2. 【重拾Android】(2)SQLite数据库与数据持久化
  3. Android(安卓)集成海康威视监控 SDK,实现监控录像的查看
  4. android 代码优化(2)
  5. 如何使用jdb调试android的java程序
  6. 回调函数小记
  7. Android知识梳理之Sqlite数据库的使用和优化
  8. android接入即时IM
  9. Android消息机制理解

随机推荐

  1. 2019年十大热门AI岗位及薪资报告:算法工程
  2. 一文理解 Transformer 的工作原理
  3. 自动驾驶狂欢落幕:靠一个demo就敢宣称落地
  4. “AI新贵”图神经网络算法及平台在阿里的
  5. AI首次实现秒级“自主判案”!阿里达摩院颠
  6. 【点宽专栏】知识分享:验证CAPM模型在中国
  7. 如何基于Flink+TensorFlow打造实时智能异
  8. 谁在“谋杀” Hadoop?
  9. 机器学习陷入困境!谷歌大脑专家发文吐槽AI
  10. “看一看”推荐模型揭秘!微信团队提出实时