浅谈Android线程通信之Handler

做安卓开发两年多了,到现在才弄清楚Handler的实现机制。实在是惭愧,主要是之前的偷懒,知道怎么用就得了。后来公司使用EventBus,简化了跨线程的事件传递。大大方便了开发,但是同时也会对性能有所影响,但是几乎的可以忽略的。EventBus框架并不玄乎,其实是一个把Handler玩的很溜的人,利用java反射机制所创造出来的这么一个神奇的事件传递机制。然而它真的很有卵用。
但是为了应付面试,我还是硬着头皮去了解了Handler的实现过程。
现在我把这两天所理解的Handler机制来和大家说说。
先说一下Handler最简单的使用方法:
比如我们要在多线程中(非主线程)去更新一个控件view的状态。然而,android不允许我们这么做。更新UI相关的操作必须在主线程,特例:progressBar的进度更新除外setProgress
private void mainThreadTest(){

        final Handler handler = new Handler(){

            @Override
            public void handleMessage(Message msg) {
                super.handleMessage(msg);
                textView.setText("更新UI");
            }

        };

        new Thread(){

            @Override
            public void run() {
                super.run();
                handler.sendEmptyMessage(0);
            }

        }.start();
    }
上述代码看着简单,其实很容易让人忽略一个问题。就是Handler对象在什么地方初始化。我们现在用的是空的构造函数,若是放在异步线程run方法内中去new Handler();程序就会报错,说该线程没有Looper对象。到此引入了第二个关键的类Looper
每一个Handler在初始化的时候都需要一个Looper对象,如果外部构造函数没有传入Looper,它就会从初始化它的这个线程中去拿。
        mLooper = Looper.myLooper();
        if (mLooper == null) {
            throw new RuntimeException(
                "Can't create handler inside thread that has not called Looper.prepare()");
        }
        mQueue = mLooper.mQueue;
        mCallback = null;

Looper.myLooper方法其实就是获取当前Thread的Looper对象,主线程MainThread在创建的时候,就会给自己创建一个MainLooper,安卓系统已经帮我们初始化好这个Looper了,所以我们可以肆无忌惮的在主线程中new Handler()。

既然每一个Handler都要有自己的Looper,这个Looper肯定很重要,他有他的专属部下MessageQueue,他是MessageQueue消息队列的管理员。通过调用Looper.loop()方法把他所管理的消息队列(MessageQueue)中的消息(Message)依次取出来,交给他的领导Handler来处理。
上面那段话基本囊括了Handler、Message、MessageQueue、Looper的关系。下面再提下日常使用中的一些注意点。

1.注意给新建线程初始化该Thread的专属Looper
new Thread(){

            @Override
            public void run() {
                super.run();
                Looper.prepare();
                Handler handler = new Handler();
                //handler.sendEmptyMessage(0);
                //Looper.loop();
            }

        }.start();
如果不加Looper.prepare();程序会报异常。该方法中就是new 了一个Looper对象,并把该Looper对象和Thread绑定。

2.避免重复创建过多的Message对象
使用过程中,我们需要发送Message消息,可以通过Message.obtain()来获取消息对象,若公共消息池中有消息对象,就会reset然后返回,若没有则初始化一个Message对象。可以避免线程中频繁的消息对象创建,造成内存泄露。

未完待续,明天要去面试,完了再整理,先到这里吧,
转载请注明出处!!!!

你可能感兴趣的:(android,事件,handler)