Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android中利用Handler實現消息的分發機制(三)

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

編輯:關於Android編程

在第二篇文章《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 : 1
10-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 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

這樣,我們就能夠將業務邏輯和數據操作給分開了,實現了對功能編程。

雖然只是一個不是很成熟的想法,但還是希望能夠跟大家分享一下,在設計代碼架構的時候,能夠根據功能,業務需求或者基礎框架來進行分層,分塊,實現代碼的松耦合。

結束。





  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved