Handler: 主線程如何通知子線程

來源:互聯網
上載者:User

在 android 中,不可以在子線程中更新 UI 的操作,否則會報錯或者異常資訊。


在這種情況下,我們會使用 Handler(在 UI 線程建立該對象) 接收子線程的訊息更新 UI.


可以看出,這是子線程通知主線程,而主線程沒有直接通知子線程,那麽我們如何做到這一點?這樣有什麼好處?
好處,很明顯。主線程中如果有些耗時的操作,我們可以讓子線程去做,這時,主線程就可以通知子線程了!

實現這種操作的方式有很多,今天主要想說說 HandlerThread 與 Handler 的配合使用方法。

在主線程中,可以建立 HandlerThread 對象:
        HandlerThread mHandlerThread = new HandlerThread("sub_thread");
        mHandlerThread.start();

這樣,就開啟了一個子線程,該線程的名字就是 sub_thread.

然後,我們實現一個繼承自 Handler 的 MyHandler 類:
class MyHandler extends Handler {

        public MyHandler() {
            super();
        }

        public MyHandler(Looper looper) {
            super(looper);
        }
        
        @Override
        public void handleMessage(Message msg) {
            // super.handleMessage(msg);
            if(msg.what == MSG_WHAT) {
                Bundle bundle = msg.getData();
                String info = bundle.getString("main");
                Log.d("mark", "我接受任務:" + info);
            }
        }
    }

最後,使用 Message 來傳遞訊息,MyHandler 會根據情況處理 Message.

完整代碼:
package mark.zhang;

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

public class HandlerThreadActivity extends Activity {

    private static final int MSG_WHAT = 1;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        
        // 建立對象,並啟動該線程
        HandlerThread mHandlerThread = new HandlerThread("sub_thread");
        mHandlerThread.start();
        // 擷取 Looper 對象
        MyHandler mHandler = new MyHandler(mHandlerThread.getLooper());
        // 建立 Bundle 對象,傳遞資料
        Bundle bundle = new Bundle();
        bundle.putString("main", "我這邊事情太多,麻煩你幫忙處理一下!");
        // 發送訊息
        Message msg = new Message();
        msg.what = MSG_WHAT;
        msg.setData(bundle);
        msg.setTarget(mHandler);
        msg.sendToTarget();
        
        Log.d("mark", "UI----" + "threadName: " + Thread.currentThread().getName() + ",threadId: " + Thread.currentThread().getId());
    }

    /**
     * 該Handler調用 handleMessage方法運行在子線程
     * 
     * @author mark
     */
    class MyHandler extends Handler {

        public MyHandler() {
            super();
        }
        
        /* 這個構造方法必須有 */
        public MyHandler(Looper looper) {
            super(looper);
        }

        @Override
        public void handleMessage(Message msg) {
            if (msg.what == MSG_WHAT) {
                Bundle bundle = msg.getData();
                // 接收訊息
                String info = bundle.getString("main");
                Log.d("mark", "handleMessage---" + "threadName: " + Thread.currentThread().getName() + ",threadId: " + Thread.currentThread().getId());
                Log.d("mark", "我接受任務:" + info);
            }
        }
    }
}

這裡,我們思考一個問題,代碼:
 // 擷取 Looper 對象
 MyHandler mHandler = new MyHandler(mHandlerThread.getLooper());

擷取 Looper 對象,使用的是 HandlerThread 對象的 getLooper 對象。為什麼不直接這樣:
// 擷取 Looper 對象
MyHandler mHandler = new MyHandler(getMainLooper());

如果這樣做的話,列印資訊如下:
D/mark    (21852): UI----threadName: main,threadId: 1
D/mark    (21852): handleMessage---threadName: main,threadId: 1
D/mark    (21852): 我接受任務:我這邊事情太多,麻煩你幫忙處理一下!

可見,此時的 handleMessage 是在主線程中啟動並執行。每個主線程預設有一個 Looper,也就是說在主線程中,下面代碼是等效的:

  MyHandler mHandler = new MyHandler(getMainLooper());
  MyHandler mHandler = new MyHandler();

但是子線程需要手動擷取如:
MyHandler mHandler = new MyHandler(mHandlerThread.getLooper());

實現主線程、子線程雙向通訊可以在各自的線程中分別是用 Handler 來傳遞資訊和處理訊息。



聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.