博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
对Android Handler Message Looper常见用法,知识点的一些总结
阅读量:5759 次
发布时间:2019-06-18

本文共 8345 字,大约阅读时间需要 27 分钟。

hot3.png

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

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

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

 

Class Overview

 

A Handler allows you to send and process  and Runnable objects associated with a thread's. 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的构造函数

 

  • ()   Default constructor associates this handler with the  for the current thread.
  • ( callback) Constructor associates this handler with the for the current thread and takes a callback interface in which you can handle messages.
  •  
  • ( looper)  Use the provided  instead of the default one.
  •  
  • ( looper,  callback)  Use the provided  instead of the default one and take a callback interface in which to handle messages.

 

 

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

 

   ( callback)可以截获消息,

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

 

2. 关于Message

 

 

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

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

 

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

 

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对象

( 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()为例

[java]  

  1. public class Test1 extends Activity implements OnClickListener {  
  2.   
  3.     private TextView tv;  
  4.     private Button btn;  
  5.     private int i = 0;  
  6.   
  7.     Handler handler = new Handler() {  
  8.         public void handleMessage(Message msg) {  
  9.             tv.setText("Hello 改变了"+i++);  
  10.             handler.sendEmptyMessageDelayed(0, 1 * 1000); //延迟一秒发送  
  11.   
  12.         };  
  13.     };  
  14.   
  15.       
  16.     protected void onCreate(Bundle savedInstanceState) {  
  17.         super.onCreate(savedInstanceState);  
  18.         setContentView(R.layout.test1);  
  19.         setView();  
  20.         test1();  
  21.   
  22.     }  
  23.   
  24.     private void setView() {  
  25.         tv = (TextView) this.findViewById(R.id.tv);  
  26.         btn = (Button) this.findViewById(R.id.btn);  
  27.         btn.setOnClickListener(this);  
  28.     }  
  29.   
  30.     private void test1() {  
  31.   
  32.         new Thread() {  
  33.             public void run() {  
  34.   
  35.                 handler.sendEmptyMessageDelayed(0, 1 * 1000); //延迟一秒发送  
  36.             };  
  37.         }.start();  
  38.     }  
  39.   
  40.       
  41.     public void onClick(View v) {  
  42.         switch (v.getId()) {  
  43.   
  44.         case R.id.btn:  
  45.             handler.removeMessages(0);//移除消息  
  46.             break;  
  47.   
  48.         default:  
  49.             break;  
  50.         }  
  51.   
  52.     }  
  53.   
  54. }  

 

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

 

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

[java]  

  1. public class Test2 extends Activity implements OnClickListener {  
  2.   
  3.     private TextView tv;  
  4.   
  5.   
  6.     Handler handler = new Handler() {  
  7.         public void handleMessage(Message msg) {  
  8.               
  9.             tv.setText("msg.what=" + msg.what + ",     msg.arg1=" + msg.arg1  
  10.                     + ",    msg.arg2=" + msg.arg2 + ",    msg.obj=" + msg.obj);  
  11.   
  12.         };  
  13.     };  
  14.   
  15.       
  16.     protected void onCreate(Bundle savedInstanceState) {  
  17.         super.onCreate(savedInstanceState);  
  18.         setContentView(R.layout.test2);  
  19.         setView();  
  20.         test();  
  21.   
  22.     }  
  23.   
  24.     private void setView() {  
  25.         tv = (TextView) this.findViewById(R.id.tv);  
  26.   
  27.     }  
  28.   
  29.     private void test() {  
  30.   
  31.         new Thread() {  
  32.             public void run() {  
  33.   
  34.                 Message msg = new Message();  
  35.                 UserBean userBean = new UserBean();  
  36.                 userBean.setName("Jim");  
  37.                 userBean.setPwd("123456");  
  38.                 msg.what = 1;  
  39.                 msg.arg1 = 2;  
  40.                 msg.arg2 = 3;  
  41.                 msg.obj = userBean;  
  42.                 handler.sendMessage(msg);  
  43.             };  
  44.         }.start();  
  45.     }  
  46.   
  47.       
  48.     public void onClick(View v) {  
  49.         switch (v.getId()) {  
  50. //  
  51. //      case R.id.btn:  
  52. //          handler.removeMessages(0);//移除消息  
  53. //          break;  
  54.   
  55.         default:  
  56.             break;  
  57.         }  
  58.   
  59.     }  
  60.   
  61. }  

实体类

[java]  

  1. public class UserBean {  
  2.   
  3.     public String name;  
  4.       
  5.     public String pwd;  
  6.   
  7.     public String getName() {  
  8.         return name;  
  9.     }  
  10.   
  11.     public void setName(String name) {  
  12.         this.name = name;  
  13.     }  
  14.   
  15.     public String getPwd() {  
  16.         return pwd;  
  17.     }  
  18.   
  19.     public void setPwd(String pwd) {  
  20.         this.pwd = pwd;  
  21.     }  
  22.   
  23.       
  24.     public String toString() {  
  25.         return "UserBean [name=" + name + ", pwd=" + pwd + "]";  
  26.     }  
  27.       
  28.       
  29. }  

 

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

 

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

[java]  

  1. public class Test3 extends Activity implements OnClickListener {  
  2.   
  3.     private TextView tv;  
  4.   
  5.     Handler handler = new Handler() {  
  6.         public void handleMessage(Message msg) {  
  7.   
  8.             tv.setText("msg.what=" + msg.what + ",     msg.arg1=" + msg.arg1  
  9.                     + ",    msg.arg2=" + msg.arg2 + ",    msg.obj=" + msg.obj);  
  10.   
  11.         };  
  12.     };  
  13.   
  14.     @Override  
  15.     protected void onCreate(Bundle savedInstanceState) {  
  16.         super.onCreate(savedInstanceState);  
  17.         setContentView(R.layout.test3);  
  18.         setView();  
  19.         test();  
  20.   
  21.     }  
  22.   
  23.     private void setView() {  
  24.         tv = (TextView) this.findViewById(R.id.tv);  
  25.   
  26.     }  
  27.   
  28.     private void test() {  
  29.   
  30.         new Thread() {  
  31.             public void run() {  
  32.   
  33.                 // Message msg = new Message();  
  34.                 Message msg = handler.obtainMessage();  
  35.                 UserBean userBean = new UserBean();  
  36.                 userBean.setName("Jim");  
  37.                 userBean.setPwd("123456");  
  38.                 msg.what = 1;  
  39.                 msg.arg1 = 2;  
  40.                 msg.arg2 = 3;  
  41.                 msg.obj = userBean;  
  42.                 // handler.sendMessage(msg);n  
  43.                 msg.sendToTarget();  
  44.             };  
  45.         }.start();  
  46.     }  
  47.   
  48.     @Override  
  49.     public void onClick(View v) {  
  50.         switch (v.getId()) {  
  51.         //  
  52.         // case R.id.btn:  
  53.         // handler.removeMessages(0);//移除消息  
  54.         // break;  
  55.   
  56.         default:  
  57.             break;  
  58.         }  
  59.   
  60.     }  
  61.   
  62. }  

效果和上图一样

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

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

[java]  

  1. public class Test4 extends Activity implements OnClickListener {  
  2.   
  3.     private TextView tv;  
  4.     private Button btn;  
  5.     private int i = 0;  
  6.   
  7.     Handler handlerPost = new Handler();  
  8.     // 线程中运行该接口的run函数  
  9.     Runnable update_thread = new Runnable() {  
  10.         public void run() {  
  11.             // System.out.println("activity_id---->"+Thread.currentThread().getId());  
  12.             // System.out.println("activity_name---->"+Thread.currentThread().getName());  
  13.             tv.setText("handlerPost:"+i++);  
  14.             // 延时1s后又将线程加入到线程队列中  
  15.             handlerPost.postDelayed(update_thread, 1000);  
  16.   
  17.         }  
  18.     };  
  19.   
  20.     @Override  
  21.     protected void onCreate(Bundle savedInstanceState) {  
  22.         super.onCreate(savedInstanceState);  
  23.         setContentView(R.layout.test4);  
  24.         setView();  
  25.         System.out  
  26.                 .println("activity_id0---->" + Thread.currentThread().getId());  
  27.         System.out.println("activity_name0---->"  
  28.                 + Thread.currentThread().getName());  
  29.         test();  
  30.   
  31.     }  
  32.   
  33.     private void setView() {  
  34.         tv = (TextView) this.findViewById(R.id.tv);  
  35.         btn = (Button) this.findViewById(R.id.btn);  
  36.         btn.setOnClickListener(this);  
  37.     }  
  38.   
  39.     private void test() {  
  40.   
  41.         // 将线程接口立刻送到线程队列中  
  42.         handlerPost.post(update_thread); // handler使用了post方法启动了runnbale,其实启动的线程和activity主线程是同一个线程  
  43.         // Thread t = new Thread(update_thread);  
  44.         // //这样绑定的线程与它所在的activity线程就不是同一个线程了  
  45.         // t.start();  
  46.     }  
  47.   
  48.     @Override  
  49.     public void onClick(View v) {  
  50.         switch (v.getId()) {  
  51.   
  52.         case R.id.btn:  
  53.             handlerPost.removeCallbacks(update_thread);// 将接口从线程队列中移除  
  54.             break;  
  55.   
  56.         default:  
  57.             break;  
  58.         }  
  59.   
  60.     }  
  61.   
  62. }  

说明:

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

如果使用

Thread t = new Thread(update_thread);

t.start();

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

效果图:

 

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

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

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

 

[java]  

  1. public class Test5 extends Activity implements OnClickListener {  
  2.   
  3.     private TextView tv;  
  4.     HandlerThread handThread;  
  5.     Handler handler;  
  6.   
  7.     @Override  
  8.     protected void onCreate(Bundle savedInstanceState) {  
  9.         super.onCreate(savedInstanceState);  
  10.         setContentView(R.layout.test5);  
  11.         setView();  
  12.         test();  
  13.   
  14.     }  
  15.   
  16.     private void setView() {  
  17.         tv = (TextView) this.findViewById(R.id.tv);  
  18.   
  19.     }  
  20.   
  21.     private void test() {  
  22.           
  23.         // HandlerThread  
  24.         handThread = new HandlerThread("handThread");  
  25.         handThread.start();  
  26.         handler = new Handler(handThread.getLooper()) {  
  27.             public void handleMessage(Message msg) {  
  28.   
  29.                 tv.setText("HandlerThread");  
  30.   
  31.             };  
  32.         };  
  33.         handler.sendEmptyMessage(0);  
  34.     }  
  35.   
  36.     @Override  
  37.     public void onClick(View v) {  
  38.         switch (v.getId()) {  
  39.         //  
  40.         // case R.id.btn:  
  41.         // handler.removeMessages(0);//移除消息  
  42.         // break;  
  43.   
  44.         default:  
  45.             break;  
  46.         }  
  47.   
  48.     }  
  49.   
  50. }  

效果图:

 

Demo下载地址:

转载于:https://my.oschina.net/JiangTun/blog/1827958

你可能感兴趣的文章
Git原理与高级使用(3)
查看>>
从JDK源码看Writer
查看>>
Express 结合 Webpack 实现HMRwi
查看>>
基于protobuf的RPC实现
查看>>
JAVA的对象复制
查看>>
我的友情链接
查看>>
HAProxy负载均衡原理及企业级实例部署haproxy集群
查看>>
开源中国动弹客户端实践(三)
查看>>
Win 8创造颠覆性体验:预览版关键更新
查看>>
vim在多文件中复制粘贴内容
查看>>
Android ContentObserver
查看>>
文章“关于架构优化和设计,架构师必须知道的事情”
查看>>
疯狂java学习笔记1002---非静态内部类
查看>>
ISA2006实战系列之一:实战ISA三种客户端部署方案(上)
查看>>
TCP服务器
查看>>
U-Mail邮件系统与泛微OA系统一体化操作指南
查看>>
AC旁挂三层交换机管理ap,二层接入ap心得
查看>>
JS中比较数字大小
查看>>
springcloud 学习-eureka搭建-为eureka添加认证
查看>>
jQuery插件的开发
查看>>