1. 程式人生 > >Android 之 Handler

Android 之 Handler

前言:

        本編文章純粹個人見解,如有錯誤或者不到位的地方,請大家指出,多謝。

組成:

        一、Message

        二、Handler

        三、MessageQueue

        四、Looper

介紹:

    Message:

        執行緒間通訊的資訊載體。

        可將關鍵的物件,資料裝在一個Message類中發給其他執行緒(一般是主執行緒)。

    Handler:

        主要負責傳送和處理Message。

    MessageQueue:

        主要負責存放由handler發出的Message。

        每個執行緒只有一個MessageQueue物件。

    Looper:

        主要負責將MessageQueue中的Message拿個Handler處理。

        每個執行緒只有一個Looper物件。

大致流程圖:


上圖來自郭霖的 《第一行程式碼》

(子)Handler → Message → MessageQueue → Message → Looper → Message → (主)Handler

如何使用:

第一步:在主執行緒新建一個Handler並重寫handleMessage()方法。

第二步:在子執行緒新建一個Message類並打包好要傳送的資料,呼叫handler.sendMessage()。

先來一個簡單的例子:

子執行緒傳送訊息,改變button的內部文字

public class MainActivity extends AppCompatActivity {

    private Button sendBtn;
    private static final int CHANGE_BUTTON = 1;
    private Handler mHandler = new Handler(new Handler.Callback() {
        @Override
        public boolean handleMessage(Message msg) {
            switch (msg.what) {
                case CHANGE_BUTTON:
                    sendBtn.setText("Handler");
                    break;
            }
            //以前handlerMessage沒有返回值,現在要返回boolean
            //應該是根據boolean值判斷handleMessage方法是否執行完畢
            return true;
        }
    });

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        sendBtn = findViewById(R.id.sendBtn);
        sendBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        Message msg = new Message();
                        msg.what = CHANGE_BUTTON;
                        mHandler.sendMessage(msg);
                    }
                }).start();
            }
        });
    }
}

效果圖:


Message可以包含什麼資訊呢?

如果你覺得上面的博文還是不夠包含你想傳送的資訊。

你可以自己建立一個類,把你想發的資訊都裝進去。

我做個小小的例子:

    1.寫個實體類

    2.將實體類放進Bundle裡,再將Bundle放進Message裡

public class Data implements Serializable{
    private String str;
    private long l;
    private float flo;

    /* 以下省略setter 和 getter */
}
sendBtn.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                //設定好自定義的實體類
                Data data = new Data();
                data.setStr("hello");
                data.setL(32464651231234L);
                data.setFlo(1.67f);

                //將實體類放進Bundle裡
                Bundle mBundle = new Bundle();
                mBundle.putSerializable("SER_KEY", data);

                //使用setData將想傳送的資訊一起發出去
                Message msg = new Message();
                msg.what = CHANGE_BUTTON;
                msg.setData(mBundle);
                mHandler.sendMessage(msg);
            }
        }).start();
    }
});
private Handler mHandler = new Handler(new Handler.Callback() {
    @Override
    public boolean handleMessage(Message msg) {
        switch (msg.what) {
            case CHANGE_BUTTON:
                Bundle bundle = msg.getData();
                Data data = (Data) bundle.getSerializable("SER_KEY");
                if (data != null) {
                    sendBtn.setText(data.getStr());
                }
                break;
        }
        return true;
    }
});

Handler的優缺點:


優點:

        結構比較清晰,如果有多個後臺任務並行進行多個UI操作,Handler是很方便的。

缺點:

        如果只有一個後臺任務那就會顯得程式碼過多和結構複雜。

        因為我的例子只有封裝資訊,

        根本沒有進行後臺耗時操作,例如I/O,網路,資料庫操作,所以感覺不出來。

如果大家想了解關於Handler的原始碼,可以訪問以下或其他博文