Android Handler机制

Handler机制是Android中最神奇的机制之一
主要应用:
1. 定时、延迟执行
2. 跨页面传递数据发起事件
3. 跨线程执行

Handler机制分为:Handler、Loop、MessageQueue、Message四个类

关系:一个Thread对应一个Loop,一个Loop对应一个MessageQueue,一个MessageQueue对应多个Message,一个Message对应一个Handler

Handler关系类图:
Handler关系类图

Handler运行流程图:
Handler运行流程图

Question:

1.子线程是如何将runnable post到主线程运行的?

答:其实在自线程中运行runnable.post方法,真正的作用:
1. Message.obtion一个Message
2. Message.callback = runnable ,将runnable赋值给message的callback变量
3. 执行了MessageQueue.enqueueMessage方法,将此Message添加到Message通过next指针构成的列表头部(或者头部第二个)
4. 调用nativeWake(mPtr);通知MessageQueue中的nativePollOnce(ptr, nextPollTimeoutMillis);苏醒
5. 继续在他之前运行的线程中(这里是主线程)运行next()抓取Message,交给Looper.loop
6. loop调用Message对应Handler的dispatchMessage方法
7. 调用Handler的handleCallback方法
8. 最终执行message.callback.run()
最终在主线程中跑完了这个runnable方法

2.Looper.looper()、MessageQueue.next为何不会阻塞?

答:其实流程图已经给出了答案:
 MessageQueue.next()方法会调用nativePollOnce(ptr, nextPollTimeoutMillis);进行休息,让本线程的其它逻辑先运行,发现有新的Message通过MessageQueue的enqueueMessage()方法添加,会调用nativeWake(mPtr);通知nativePollOnce(ptr, nextPollTimeoutMillis);苏醒继续执行。运行结束之后又会继续休息,循环往复

3.handler为何会导致内存泄漏?如何避免?

 答:handler可以通过xxxdelay()方法,延迟dispatchMessage运行,如果在等待的这段时间相应Activity关闭掉,那么之前发出去的message内部还通过target持有handler对象,而handler为activity的内部成员,所以这段时间内activity会因为内部成员handler无法被释放而无法释放内存,故这段时间内会导致内存泄漏。
 
解决办法:handler.removeCallbacksAndMessages(null);
会调用MessageQueue的removeCallbacksAndMessages方法
内部的逻辑是如果参数为null,那么会调用当前线程所有的Message的recycleUnchecked方法,此方法会将内部所有变成置空,等待垃圾回收器回收。

4.message为何不会分发到错误的handler?

 答:因为每个Message有一个target变量指定了其所需要运行的Handler

5.子线程如何创建并使用handler?

package com.test.looper;

import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.util.Log;

public class MainActivity extends Activity {
    private LooperThread  looperThread;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        looperThread = new LooperThread();
        looperThread.start();
        looperThread.getHandler().sendEmptyMessage(1);
    }

    class LooperThread extends Thread {
        private Handler mHandler;
        private final Object mSync = new Object();

        public void run() {
        // 自线程中需要手动Looper.prepare以及手动loop
        // 需要注意的是:在创建Handler之前需要先执行Looper.prepare
            Looper.prepare();
            synchronized (mSync) {
                mHandler = new Handler(){
                    @Override
                    public void handleMessage(Message msg) {
                        Log.d("CYQ", "--->" + msg);
                    }
                };
                mSync.notifyAll();
            }
            Looper.loop();
        }

        public Handler getHandler() {
            synchronized (mSync) {
                if (mHandler == null) {
                    try {
                        mSync.wait();
                    } catch (InterruptedException e) {
                    }
                }
                return mHandler;
            }
        }
        public void exit() {
            getHandler().post(new Runnable(){
                public void run() {
                    Looper.myLooper().quit();
                }});
        }
    }
}

面试中还有时候会问:如何实现主线程向子线程发送消息?(上面的代码就是答案)

其实了解Handler机制之后,道理都一样的:
 仅仅是在主线程中调用自线程的handler,发送消息,子线程自己会通过MessageQueue.next方法跑子线程的message

自己写了个Handler工具类,方便各线程获取自己线程的Handler、主线程的Handler:

/**
 * Handler帮助类
 * 
 * @author yuanyang
 * 
 */
public class HandlerUtils {

    private HandlerUtils() {
    }

    private static class Holder {
        public static HandlerUtils instance = new HandlerUtils();
    }

    public static HandlerUtils getInstance() {
        return Holder.instance;
    }

    private Handler mHandler;

    /**
     * 获取新Handler,子线程没有Looper就用主线程的Handler
     */
    public Handler getNewHandler() {
        Looper myLooper = Looper.myLooper();
        Looper mainLooper = Looper.getMainLooper();
        if (myLooper == null) {
            mHandler = new Handler(mainLooper);
        } else {
            mHandler = new Handler(myLooper);
        }
        return mHandler;
    }

    /**
     * 获取新Handler,子线程没有Looper就用主线程的Handler
     */
    public Handler getNewHandlerCB(final HandlerDispose hd) {
        Looper myLooper = Looper.myLooper();
        Looper mainLooper = Looper.getMainLooper();
        if (myLooper == null) {
            mHandler = new Handler(mainLooper) {
                @Override
                public void handleMessage(Message msg) {
                    super.handleMessage(msg);
                    hd.handleMessage(msg);
                }
            };
        } else {
            mHandler = new Handler(myLooper) {
                @Override
                public void handleMessage(Message msg) {
                    super.handleMessage(msg);
                    hd.handleMessage(msg);
                }
            };
        }
        return mHandler;
    }

    /**
     * 获取子线程Handler
     */
    public Handler getNewChildHandler() {
        Looper myLooper = Looper.myLooper();
        if (myLooper == null) {
            Looper.prepare();
            mHandler = new Handler(Looper.myLooper());
            Looper.loop();
        } else {
            mHandler = new Handler(myLooper);
        }
        return mHandler;
    }

    /**
     * 获取子线程Handler
     */
    public Handler getNewChildHandlerCB(final HandlerDispose hd) {
        Looper myLooper = Looper.myLooper();
        if (myLooper == null) {
            Looper.prepare();
            mHandler = new Handler() {
                @Override
                public void handleMessage(Message msg) {
                    super.handleMessage(msg);
                    hd.handleMessage(msg);
                }
            };
            Looper.loop();
        } else {
            mHandler = new Handler(myLooper) {
                @Override
                public void handleMessage(Message msg) {
                    super.handleMessage(msg);
                    hd.handleMessage(msg);
                }
            };
        }
        return mHandler;
    }

    /**
     * 获取UI线程Handler
     */
    public Handler getUIHandler() {
        // 若成员变量Handler为
        if (mHandler != null) {
            if (mHandler.getLooper() == Looper.getMainLooper()) {
                return mHandler;
            }
        }
        Looper mainLooper = Looper.getMainLooper();
        mHandler = new Handler(mainLooper);
        return mHandler;
    }

    /**
     * 获取UI线程Handler
     */
    public Handler getUIHandlerCB(final HandlerDispose hd) {
        Looper mainLooper = Looper.getMainLooper();
        mHandler = new Handler(mainLooper) {
            @Override
            public void handleMessage(Message msg) {
                super.handleMessage(msg);
                hd.handleMessage(msg);
            }
        };
        return mHandler;
    }

    /**
     * UI界面关闭的时候清空Handler,方式内存泄漏
     */
    public void UIOnFinish() {
        mHandler = null;
    }

    /**
     * Handler的回调接口
     * 
     * @author yuanyang
     * 
     */
    public interface HandlerDispose {
        public void handleMessage(android.os.Message msg);
    }
}
发布了39 篇原创文章 · 获赞 9 · 访问量 9万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章