每一个学习Android的同学都会觉得Handler是一个神奇的东西,我也一样,开始我以为我懂了Handler的机制,后来发现自己是一知半解,昨天想想,我能否自己实现一个Handler,让子线程与ActivityUI线程通信,如果能够自己实现一个Handler,那必然是对Handler的消息传递机制理解渗透了。
一、引入
Android的UI是单线程控制的,实际上,成功的UI框架都是基于单线程的,多线程的UI框架往往因为解决并发和死锁的艰难而胎死腹中。只有UI线程能控制界面控件,但我们总是希望子线程的数据能更新到UI上,于是就有了Handler,它帮助我们实现了非UI线程向UI线程之间的通信,Handler的使用非常简单。
一个简单的示例,让一个TextView动态显示秒数:
1 public class MainActivity extends Activity { 2 private static final int UPDATE_TAG = 0x01; 3 private TextView textView; 4 5 @Override 6 protected void onCreate(Bundle savedInstanceState) { 7 super.onCreate(savedInstanceState); 8 setContentView(R.layout.activity_main); 9 textView = (TextView) findViewById(R.id.textview); 10 // 启动一个线程 11 new Thread(new Runnable() { 12 13 @Override 14 public void run() { 15 int count = 1; 16 while (true) { 17 // 发送计数值到handler 18 mHandler.obtainMessage(UPDATE_TAG, String.valueOf(count)) 19 .sendToTarget(); 20 try { 21 TimeUnit.SECONDS.sleep(1); 22 } catch (InterruptedException e) { 23 e.printStackTrace(); 24 } 25 } 26 } 27 28 }).start(); 29 } 30 31 public Handler mHandler = new Handler() { 32 public void handleMessage(Message msg) { 33 switch (msg.what) { 34 case UPDATE_TAG: 35 // 显示计数值 36 textView.setText((String)msg.obj); 37 break; 38 } 39 } 40 }; 41 }
通过开启一个线程,线程每隔一秒发送一次计数给handler,让handler来更新TextView的内容,新开的子线程里面不能直接操控TextView,因为这违反了UI线程了单线程控制规范,如果你真要这么做,一运行就会得到CalledFromWrongThreadException异常。
二、这不就是一个观察着模式么?
最初自己理解的Handler就是一个典型的观察着模式。sendToTarget()这个方法一定以某种方式调用了Handler的 handleMessage(Message msg)方法,从而完成了我们指定的任务,于是我写了下面这样一个Handler和Message
/*** * 模拟Android的Handler,申明一个供子类覆盖的方法和多个生成消息的方法 */ public class Handler { /*** * 子类覆盖本方法,实现想要的操作 * * @param msg */ protected void handleMessage(Message msg) { } public Message obtainMessage(int what) { Message msg = new Message(this, what, -1, -1, null); return msg; } public Message obtainMessage(int what, Object obj) { Message msg = new Message(this, what, -1, -1, obj); return msg; } public Message obtainMessage(int what, int arg1, int arg2, Object obj) { Message msg = new Message(this, what, arg1, arg2, obj); return msg; } }
下来就是Message类:
/** * * 模拟Android的Message,这里为方便演示,只写了一个构造方法。构造方法中绑定了一个Handler */ public class Message { private final Handler target; public final int what; public final int arg1; public final int arg2; public final Object obj; public Message(Handler target, int what, int arg1, int arg2, Object obj) { this.target = target; this.arg1 = arg1; this.arg2 = arg2; this.what = what; this.obj = obj; } /*** * 利用OOP的多态,调用子类的覆盖方法 */ public void sendToTarget() { target.handleMessage(this); } }
测试代码如下:
public class HandlerTest { public static void main(String[] args) { new Thread(new MyTask(Myhandler)).start(); } static class MyTask implements Runnable { private Handler handler; public MyTask(Handler handler) { this.handler = handler; } @Override public void run() { while (true) { handler.obtainMessage(0, this.toString()).sendToTarget(); } } } static Handler Myhandler = new Handler() { @Override public void handleMessage(Message msg) { switch (msg.what) { case 0: System.out.println("I am zero " + (String) msg.obj); break; } } }; }