移动应用
583
一、概念
1、事件驱动型
什么是事件驱动?就是有事了才去处理,没事就躺着不动。假如把用户点击按钮,滑动页面等这些都看作事件,事件产生后程序就执行相应的处理方法,就是属于事件驱动型。
2、消息循环
把需要处理的事件表示成一个消息,并且把这个消息放入一个队列。消息循环就是一循环,for或者while都一样。从消息队列里面取出未处理的消息,然后调用该消息的处理方法。
3、Handler
最开始碰到handler是需要在子线程里面更新UI的时候。android的UI更新只能在主线程中进行,但是在子线程中执行的逻辑又需要更新UI,例如文件下载,在子线程中访问网络下载之后,就是更新下载进度。这个时候就需要使用Hanlder,准确的说是要发送一个进度更新的消息。什么是Handler?我的理解是消息的处理者。create消息对应一个create的Handler,destroy消息对应一个destroy的Handler。
二、实现
只是说说概念太假了,下面就来实现一个简单的消息处理机制。
1、Msg
把产生的事件用消息来表示,数据用各个参数传递。
public class Msg implements Serializable{ //序列化标识 private static final long serialVersionUID = -2414053244664115328L; //该消息的处理者。 private int handlerId; //参数。 public Object arg1; public Object arg2; //大量参数 public Object array[]; public Msg(int handlerId) { this.handlerId=handlerId; } public void setHandlerId(int handlerId) { this.handlerId=handlerId; } public int getHandleId() { return handlerId; } }
2、Handler
事件的处理者
public abstract class Handler { //唯一标识,由Looper分配 private int id; //使用该Handler的Looper private Looper looper; public Handler(Looper looper) { this.looper=looper; id=looper.addMsgHandler(this); } //消息处理函数 abstract public boolean handleMsg(Msg msg); //添加一个未处理消息。 public void sendMsg(Msg msg) { looper.addMsg(msg); } //返回该handler的信使。 public Msg obtainMsg() { return new Msg(id); } }
3、Looper
消息循环
import java.util.HashMap; import java.util.LinkedList; import java.util.Map; import java.util.Queue; public class Looper { private int handlerCount=0; //消息队列。 private Queue<Msg> msgQueue=new LinkedList<Msg>(); //消息的处理。 private Map<Integer, Handler> msgHandler=new HashMap<>(); //loop public void loop() { for(;true;) if(!msgQueue.isEmpty()) if(!distributeMsg(msgQueue.poll())) //当消息处理返回false时。程序结束。 break; } //添加处理消息的handler public int addMsgHandler(Handler handler) { handlerCount++; msgHandler.put(handlerCount,handler); return handlerCount; } //添加待处理的消息 public void addMsg(Msg msg) { msgQueue.add(msg); } //消息分发 private boolean distributeMsg(Msg msg) { Handler handler=msgHandler.get(msg.getHandleId()); if(handler!=null) { handler.handleMsg(msg); }else { //出现未知消息,程序结束。 System.out.println("exit"); return false; } return true; } }
4、模拟生命周期
abstract class Basic{ private Looper mainLooper=new Looper(); private Handler sysHandler=new Handler(mainLooper) { @Override public boolean handleMsg(Msg msg) { if(msg.arg1.equals("create")) { onCreate(); } if(msg.arg1.equals("destroy")) { onDestroy(); } return true; } }; public Basic() { Msg m=sysHandler.obtainMsg(); m.arg1="create"; sysHandler.sendMsg(m); //新获取一个Msg,不能沿用上一个。 m=sysHandler.obtainMsg(); m.arg1="destroy"; sysHandler.sendMsg(m); } public Looper getMainLooper() { return mainLooper; } /** * 生命周期 */ abstract public void onCreate(); abstract public void onDestroy(); }
上面的代码创建了一个抽象类Basic,在里面注册了一个处理create和destroy两个消息的Handler。
5、子线程调用主线程的方法。
public class Main extends Basic{ private final Handler handler =new Handler(getMainLooper()) { @Override public boolean handleMsg(Msg msg) { // TODO Auto-generated method stub System.out.println("msg.arg1="+msg.arg1+",Tid="+ Thread.currentThread().getId()); getMainLooper().addMsg(new Msg(-1)); return true; } }; public void onCreate() { System.out.println("..............onCreate"); System.out.println("mainThread Tid="+Thread.currentThread().getId()); new Thread(new Runnable() { @Override public void run() { // TODO Auto-generated method stub System.out.println("childThread Tid="+Thread.currentThread().getId()); Msg msg=handler.obtainMsg(); msg.arg1="childCall"; handler.sendMsg(msg); } }).start(); } @Override public void onDestroy() { // TODO Auto-generated method stub System.out.println(".............onDestroy"); //getMainLooper().addMsg(new Msg(-1)); } public static void main(String[] args) { new Main().getMainLooper().loop(); } }
6、结果
结果分析,首先是两个生命周期的方法被调用,其次是实现了子线程调用主线程的方法。这里子线程转到主线程的原因是因为Looper运行在主线程,消息由Looper分发处理。
广告