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();
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章