一、概念
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分发处理。