一、概念

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分发处理。