Android的消息循环与Handler机制理解

一、概念

1、事件驱动型

什么是事件驱动?就是有事了才去处理,没事就躺着不动。假如把用户点击按钮,滑动页面等这些都看作事件,事件产生后程序就执行相应的处理方法,就是属于事件驱动型。

2、消息循环

把需要处理的事件表示成一个消息,并且把这个消息放入一个队列。消息循环就是一循环,for或者while都一样。从消息队列里面取出未处理的消息,然后调用该消息的处理方法。

3、Handler

最开始碰到handler是需要在子线程里面更新UI的时候。android的UI更新只能在主线程中进行,但是在子线程中执行的逻辑又需要更新UI,例如文件下载,在子线程中访问网络下载之后,就是更新下载进度。这个时候就需要使用Hanlder,准确的说是要发送一个进度更新的消息。什么是Handler?我的理解是消息的处理者。create消息对应一个create的Handler,destroy消息对应一个destroy的Handler。

二、实现

只是说说概念太假了,下面就来实现一个简单的消息处理机制。

1、Msg

把产生的事件用消息来表示,数据用各个参数传递。

1public class Msg implements Serializable{ 2 //序列化标识 3 private static final long serialVersionUID = -2414053244664115328L; 4 5 //该消息的处理者。 6 private int handlerId; 7 8 //参数。 9 public Object arg1; 10 public Object arg2; 11 12 //大量参数 13 public Object array[]; 14 15 public Msg(int handlerId) { 16 this.handlerId=handlerId; 17 } 18 19 public void setHandlerId(int handlerId) { 20 this.handlerId=handlerId; 21 } 22 public int getHandleId() { 23 return handlerId; 24 } 25}

2、Handler

事件的处理者

1public abstract class Handler { 2 //唯一标识,由Looper分配 3 private int id; 4 5 //使用该Handler的Looper 6 private Looper looper; 7 8 public Handler(Looper looper) { 9 this.looper=looper; 10 id=looper.addMsgHandler(this); 11 } 12 13 //消息处理函数 14 abstract public boolean handleMsg(Msg msg); 15 16 //添加一个未处理消息。 17 public void sendMsg(Msg msg) { 18 looper.addMsg(msg); 19 } 20 21 //返回该handler的信使。 22 public Msg obtainMsg() { 23 return new Msg(id); 24 } 25}

3、Looper

消息循环

1import java.util.HashMap; 2import java.util.LinkedList; 3import java.util.Map; 4import java.util.Queue; 5 6public class Looper { 7 private int handlerCount=0; 8 //消息队列。 9 private Queue<Msg> msgQueue=new LinkedList<Msg>(); 10 //消息的处理。 11 private Map<Integer, Handler> msgHandler=new HashMap<>(); 12 13 //loop 14 public void loop() { 15 for(;true;) 16 if(!msgQueue.isEmpty()) 17 if(!distributeMsg(msgQueue.poll())) 18 //当消息处理返回false时。程序结束。 19 break; 20 } 21 22 //添加处理消息的handler 23 public int addMsgHandler(Handler handler) { 24 handlerCount++; 25 msgHandler.put(handlerCount,handler); 26 return handlerCount; 27 } 28 29 //添加待处理的消息 30 public void addMsg(Msg msg) { 31 msgQueue.add(msg); 32 } 33 34 //消息分发 35 private boolean distributeMsg(Msg msg) { 36 Handler handler=msgHandler.get(msg.getHandleId()); 37 if(handler!=null) { 38 handler.handleMsg(msg); 39 }else { 40 //出现未知消息,程序结束。 41 System.out.println("exit"); 42 return false; 43 } 44 return true; 45 } 46}

4、模拟生命周期

1abstract class Basic{ 2 private Looper mainLooper=new Looper(); 3 private Handler sysHandler=new Handler(mainLooper) { 4 @Override 5 public boolean handleMsg(Msg msg) { 6 if(msg.arg1.equals("create")) { 7 onCreate(); 8 } 9 if(msg.arg1.equals("destroy")) { 10 onDestroy(); 11 } 12 return true; 13 } 14 }; 15 16 public Basic() { 17 Msg m=sysHandler.obtainMsg(); 18 m.arg1="create"; 19 sysHandler.sendMsg(m); 20 //新获取一个Msg,不能沿用上一个。 21 m=sysHandler.obtainMsg(); 22 m.arg1="destroy"; 23 sysHandler.sendMsg(m); 24 } 25 26 public Looper getMainLooper() { 27 return mainLooper; 28 } 29 30 /** 31 * 生命周期 32 */ 33 abstract public void onCreate(); 34 abstract public void onDestroy(); 35}

上面的代码创建了一个抽象类Basic,在里面注册了一个处理create和destroy两个消息的Handler。

5、子线程调用主线程的方法。

1public class Main extends Basic{ 2 private final Handler handler 3 =new Handler(getMainLooper()) { 4 @Override 5 public boolean handleMsg(Msg msg) { 6 // TODO Auto-generated method stub 7 System.out.println("msg.arg1="+msg.arg1+",Tid="+ 8 Thread.currentThread().getId()); 9 getMainLooper().addMsg(new Msg(-1)); 10 return true; 11 } 12 }; 13 public void onCreate() { 14 System.out.println("..............onCreate"); 15 System.out.println("mainThread Tid="+Thread.currentThread().getId()); 16 new Thread(new Runnable() { 17 @Override 18 public void run() { 19 // TODO Auto-generated method stub 20 System.out.println("childThread Tid="+Thread.currentThread().getId()); 21 Msg msg=handler.obtainMsg(); 22 msg.arg1="childCall"; 23 handler.sendMsg(msg); 24 } 25 }).start(); 26 } 27 @Override 28 public void onDestroy() { 29 // TODO Auto-generated method stub 30 System.out.println(".............onDestroy"); 31 //getMainLooper().addMsg(new Msg(-1)); 32 } 33 public static void main(String[] args) { 34 new Main().getMainLooper().loop(); 35 } 36}

6、结果

结果分析,首先是两个生命周期的方法被调用,其次是实现了子线程调用主线程的方法。这里子线程转到主线程的原因是因为Looper运行在主线程,消息由Looper分发处理。

点赞
收藏

评论区

加载中...

相关推荐

MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1

文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s

Oracle 分组与拼接字符串同时使用

SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(

手写Java HashMap源码

HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22

每日一问(一)Handler相关知识

1、Handler负责发送Message和处理Mesage2、Message就是消息载体,可用what区分,也可传递对象3、MessageQueue消息队列,存储Message4、Looper循环取出MessageQueue里的Message交给Handler处理。5、一个线程只有一个Looper和MessageQueue,子线程中使用Handler一

Android HandlerThread源码解析

在上一章Handler源码解析文章中,我们知道App的主线程通过Handler机制完成了一个线程的消息循环。那么我们自己也可以新建一个线程,在线程里面创建一个Looper,完成消息循环,可以做一些定时的任务或者写日志的功能。这就是HandlerThread的作用AndroidHandler消息机制源码解析(https://www.cnblogs.co

Android消息循环分析

我们的常用的系统中,程序的工作通常是有事件驱动和消息驱动两种方式,在Android系统中,Java应用程序是靠消息驱动来工作的。消息驱动的原理就是:1\.有一个消息队列,可以往这个队列中投递消息;2\.有一个消息循环,不断从消息队列中取出消息,然后进行处理。在Android中通过Looper来封装消息循环,同时在其中封装了一个消息队