4. HandlerThread

1. Fundamentals

HandlerThread是一个内部包含Thread,Looper,MessageQueue的线程。HandlerThread 开启之后,它就会创建一个Looper和MessageQueue的队列,等待处理发送过来的消息。
Eg:

HandlerThread handlerThread = new HandlerThread("handlerthread");
handlerThread.start();

// 实例化Handler时,使用HandlerThread的Looper,这样实例化后的Handler属于HandlerThread线程中的,Handler发送的message就会到HandlerThread(Worker Thread)的MessageQueue中,
// 然后在Handler的handleMessage方法中处理发送来的message
mHandler = new Handler(handlerThread.getLooper()) {
    @Override
    public void handleMessage(Message msg) {
        super.handleMessage(msg);
        // TODO: process message
    }
}

如果在HandlerThread开始之前有其他额外的需要设置的,那么需要重写HandlerThread.onLooperPrepared()方法,这个方法在Looper被prepared时候会在background thread中调用。例如,我们可以在onLooperPrepared()方法中创建一个Handler,辅助HandlerThread处理消息。
Eg:

public class MyHandlerThread extends HandlerThread {
    private final String TAG = MyHandlerThread.class.getSimpleName();
    private Handler mHandler = null;

    public MyHandlerThread(String name) {
        super("myhandlerthread", Process.THREAD_PRIORITY_BACKGROUND);
    }

    @Override
    protected void onLooperPrepared() {
        super.onLooperPrepared();

        mHandler = new Handler(getLooper()) {
            @Override
            public void handleMessage(Message msg) {
                super.handleMessage(msg);
                switch (msg.what) {
                    case 1:
                        Log.i(TAG, "MyHandlerThread # onLooperPrepared # what is 1");
                        break;
                }
            }
        };
    }

    public void sendMessage1() {
        mHandler.sendEmptyMessage(1);
    }
}

2. Lifecycle

一个正在运行的HandlerThread实例对象处理接收到Message直到它被终止,一个终止的HandlerThread不能重用。

Creation

构造方法:

HandlerThread(String name)
HandlerThread(String name, int priority)

Execution

调用HandlerThread.start()方法开始运行

Reset

message queue能够被重置,重置会删除message queue中所有待处理的message,但是那些已经被diapatch出去或者正在执行的message不受影响,同时这个thread还是alive的,也能处理新发生来的message。
Eg:

public void resetHandlerThread() {
    mHandler.removeCallbackAndMessages(null);
}

Termination

第一种方法:
调用HandlerThread的quit()或者quitSafely()方法来终止,调用这个方法相当于终止了Looper。
Eg:

public void stopHandlerThread(HandlerThread handlerThread) {
    handlerThread.quit();
    // 调用interrupt()方法,这样HandlerThread就会取消正在执行的message
    handlerThread.interrupt();
}

第二种方法:
通过Handler发送一个终止任务来退出Looper,从而终止HandlerThread
Eg:

handler.post(new Runnable() {
    @Override
    public void run() {
        Looper.myLooper().quit();
    }
});

3. Demo

因为HandlerThread中MessageQueue是线性处理的,因此可以依赖这个性质,使用HandlerThread处理有顺序要求的任务。
例如使用HandlerThread处理有顺序要求的网络请求,当同一个网络请求返回成功后,才能进行下一个网络请求。
Eg:

public class ChainedNetworkActivity extends Activity {
    private static final int DIALOG_LOADING = 0;
    private static final int SHOW_DIALOG = 1;
    private static final int DISMISS_DIALOG = 2;

    private DialogHandler dialogHandler = null;
    private NetworkHandlerThread networkHandlerThread = null;

    private static class DialogHandler extends Handler {
        private WeakReference<ChainedNetworkActivity> activity = null;

        public DialogHandler(ChainedNetworkActivity activity) {
            this.activity = new WeakReference<ChainedNetworkActivity>(activity);
        }

        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            switch (msg.what) {
                case SHOW_DIALOG:
                    if (activity != null) {
                        activity.get().showDialog(DIALOG_LOADING);
                    }
                    break;

                case DISMISS_DIALOG:
                    if (activity != null) {
                        activity.get().dismissDialog(DIALOG_LOADING);
                    }
                    break;
            }
        }
    }

    private class NetworkHandlerThread extends HandlerThread {
        private final int STATE_A = 1;
        private final int STATE_B = 2;
        private Handler handler = null;

        public NetworkHandlerThread() {
            super("networkhandlerthread", Process.THREAD_PRIORITY_BACKGROUND);
        }

        @Override
        protected void onLooperPrepared() {
            super.onLooperPrepared();

            handler = new Handler(getLooper()) {
                @Override
                public void handleMessage(Message msg) {
                    super.handleMessage(msg);
                    switch (msg.what) {
                        case STATE_A:
                            dialogHandler.sendEmptyMessage(SHOW_DIALOG);
                            String resultA = network1();
                            if (resultA != null) {
                                // 当第一个网络请求成功后,进行下一个
                                sendMessage(obtainMessage(STATE_B, resultA));
                            } else {
                                dialogHandler.sendEmptyMessage(DISMISS_DIALOG);
                            }
                            break;

                        case STATE_B:
                            network2((String) msg.obj);
                            dialogHandler.sendEmptyMessage(DISMISS_DIALOG);
                            break;
                    }
                }
            };

            // 开始一个网络请求
            handler.sendEmptyMessage(STATE_A);
        }

        private String network1() {
            SystemClock.sleep(1000);
            return "State 1";
        }

        private String network2(String preResult) {
            SystemClock.sleep(1000);
            return preResult + " - State B";
        }
    }

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        dialogHandler = new DialogHandler(this);

        networkHandlerThread = new NetworkHandlerThread();
        networkHandlerThread.start();
    }

    @Override
    protected Dialog onCreateDialog(int id) {
        Dialog dialog = null;
        switch (id) {
            case DIALOG_LOADING:
                AlertDialog.Builder builder = new AlertDialog.Builder(this);
                builder.setMessage("Loading...");
                dialog = builder.create();
                break;
        }
        return dialog;
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        networkHandlerThread.quit();
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章