每一个学习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;
            }
        }
    };

}
View Code

相关文章:

  • 2022-02-08
  • 2022-12-23
  • 2021-11-13
  • 2021-06-21
  • 2021-07-30
  • 2021-12-27
  • 2022-12-23
猜你喜欢
  • 2022-12-23
  • 2021-05-27
  • 2022-02-08
  • 2022-12-23
  • 2021-04-28
  • 2022-12-23
  • 2022-12-23
相关资源
相似解决方案