Android中利用Handler實現訊息的分發機制(三)

來源:互聯網
上載者:User

標籤:

在第二篇文章《Android中利用Handler實現訊息的分發機制(一)》中,我們講到主線程的Looper是Android系統在啟動App的時候,已經幫我們建立好了,而假設在子線程中須要去使用Handler的時候,我們就須要顯式地去調用Looper的 prepare方法和loop方法,從而為子線程建立其唯一的Looper。

詳細代碼例如以下:

class LooperThread extends Thread {          public Handler mHandler;          public void run() {              Looper.prepare();              mHandler = new Handler() {                                  public void handleMessage(Message msg) {                      Log.v("Test", "Id of LooperThread : " + Thread.currentThread().getId());                      ...                     }                  }              };              Looper.loop();          }      }  

而實際上,Android SDK 中已經提供了這樣一個實現,一個叫做HandlerThread 的類,它繼承了線程,而且在其run方法中調用了Looper.prepare()  和 Looper.loop()  方法,從而建立了一個已經有Looper的線程,如以下代碼所看到的:

    @Override    public void run() {        mTid = Process.myTid();        Looper.prepare();        synchronized (this) {            mLooper = Looper.myLooper();            notifyAll();        }        Process.setThreadPriority(mPriority);        onLooperPrepared();        Looper.loop();        mTid = -1;    }

我們在主線程中定義的Handler所相應的Looper,還是屬於主線程的,那麼事實上就僅僅是實現了在主線程中的非同步處理而已。

而在日常開發中,當我們須要利用Handler在子線程中實現業務的處理的時候,我們就能夠利用HandlerIntent來實現我們的需求。

普通情況下,我們會建立一個類,讓其去繼承HandlerThread,   例如以下:

   public class MyHandlerThread extends HandlerThread {        public MyHandlerThread(String name) {                        super(name);        }    }    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        Log.v("Test", "Id of MainThread : " + Thread.currentThread().getId());        MyHandlerThread myHandlerThread = new MyHandlerThread("MyHandlerThread");        myHandlerThread.start();        Handler handler = new Handler(myHandlerThread.getLooper(), new Callback() {            @Override            public boolean handleMessage(Message msg) {                Log.v("Test", "id of Thread by Callback : " + Thread.currentThread().getId());                return false;            }        });        handler.sendEmptyMessage(0);    }

在範例中, 建立了一個MyHandlerThead 對象,記得,它是一個線程,所以須要調用其 start 方法,讓線程跑起來。

接著,就須要利用Handler當中一個建構函式Handler(Looper, Callback) ,將HandlerThread線程中的 Looper 賦給handler,而隨之傳入的,則是Handler.Callback的介面實作類別,如上面代碼所看到的。

最後調用 sendMessage方法,相應的結果例如以下:

10-28 17:24:50.438: V/Test(31694): Id of MainThread : 110-28 17:24:50.448: V/Test(31694): id of Thread by Callback : 91617

可見,handleMessage的處理邏輯已經在是在另外一個線程中去跑了。

普通情況下,我們在建立handlerThread的時候,也會順便實現Handler.Callback介面,將我們要實現的代碼邏輯也封裝在此線程中,讓代碼更具有可讀性,例如以下:

    public class MyHandlerThread extends HandlerThread implements Callback{        public MyHandlerThread(String name) {                        super(name);        }        @Override        public boolean handleMessage(Message msg) {            Log.v("Test", "id of Thread by Callback : " + Thread.currentThread().getId());            return true;        }    }    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        Log.v("Test", "Id of MainThread : " + Thread.currentThread().getId());        MyHandlerThread myHandlerThread = new MyHandlerThread("MyHandlerThread");        myHandlerThread.start();        Handler handler = new Handler(myHandlerThread.getLooper(), myHandlerThread);        handler.sendEmptyMessage(0);    }

說到代碼的可讀性,有時候,我們更加看重代碼之間的層次或者說模組化,耦合度等特點。

不同的商務邏輯,不同的功能,應該實如今不同的模組中,而模組與模組之間就能夠通過一個訊息來通訊,而這樣的訊息通訊方式,我們就能夠利用Handler和HandlerThread來實現。

比方,近期做的一個瀏覽器的小Demo,其類圖例如以下:


在當中,我們就利用了MessageDispatcher來存放各個模組的Handler,其結構例如以下:

   private static MessageDispatcher mMsgDispatcher;          private SparseArray<Handler> mHandlers;       ...    public void sendMessage(int target, int from, int msgWhat, Object obj){        Handler handler = mHandlers.get(target);        if(handler == null){            Logger.v("There is no Handler registered by target " + target);            return;        }        Message msg = handler.obtainMessage();                msg.what = msgWhat;        msg.obj = obj;        msg.arg1 = from;        handler.sendMessage(msg);            };        public void registerHanlder(int key, Handler handler){        mHandlers.put(key, handler);            }            public void unregisterHanlder(int key){        if(mHandlers.get(key) != null){            mHandlers.delete(key);        }    }        public void destroy(){        mHandlers = null;    }

在不同的模組實現中, 我們能夠調用registerHandler方法,將其對象的Handler注冊到MessageDispatcher中,然後通過sendMessage方法,指定相應的目標,假設相應的目標模組也向MessageDispatcher,就能夠獲得其Handler,然後利用其Handler來發送訊息,並由其處理。

比方,我們在BookmarkActivity中向BookmarkManager發送訊息,例如以下:

mMessageDispatcher.sendMessage(MessageConstant.TARGET_BOOKMARK_MGR, MessageConstant.TARGET_BOOKMARK_ACTIVITY,                        MessageConstant.MSG_BOOKMARK_GET_ALL_DIR, sparseArray);

而在BookmarkManager中,當其handler接受到相應的訊息的時候,其就將會進行相應的處理,例如以下:

   class BookmarkHandlerThread extends HandlerThread implements Callback{        public BookmarkHandlerThread(String name) {            super(name);                    }        @SuppressWarnings("unchecked")        public boolean handleMessage(Message msg){                   switch(msg.what){            case MessageConstant.MSG_BOOKMARK_GET_ALL_DIR:                 //Do Something

這樣,我們就行將商務邏輯和資料操作給分開了,實現了對功能編程。

儘管僅僅是一個不是非常成熟的想法,但還是希望可以跟大家分享一下,在設計代碼架構的時候,可以依據功能,業務需求或者基礎架構來進行分層,分塊,實現代碼的松耦合。

結束。





Android中利用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.