android Handler介紹(二)

從上一節的內容可以看到,handler負責發送消息到android內部提供的消息隊列中,然後在一定的時機從消息隊列將消息取出進行處理。出於安全性和偶合性的考慮,handler並不直接與消息隊列進行交互,而上通過一個名爲Looper的類來負責交互。

上一節講解的handler的用法全部都上在主線程上進行的。如果我們需要處理比較耗時的事情,就不能把handler放在主線程中了。

線程在默認的時候是沒有Looper與之相關聯。在線程中,我們可以通過調用prepare 方法來啓動一個消息loop,調用loop方法來通知Looper來處理消息,直至結束。Looper提供了很多的靜態方法來與線程、消息隊列進行交互。一個線程最多允許創建一個Looper

以下是SDK文檔中介紹的在線程中使用handler的一種方法:

class LooperThread extends Thread {

   public Handler mHandler;

        public void run() {

            Looper.prepare();

            mHandler = new Handler() {

                public void handleMessage(Message msg) {

                    // process incoming messages here

                }

            };

            Looper.loop();

        }

有一個特例, 當應用程序的進程創建時,主線程會啓動一個消息隊列和Looper,並通過該隊列管理一些優先級別比較高的對象(如Activity 等)。

考慮以下情況,定義一個全局變量mHandler

       mRunnable = new  Runnable(){

           @Override

           public void run() {

              // TODO Auto-generated method stub    

              String s = mHandler.getLooper().getThread().getName();

              Log.e("minrui", s);

              mHandler.postDelayed(mRunnable, 1000);

           }};

Thread t  = new Thread(mRunnable,"malone");

        t.start();

我們創建一個名爲“malone”的線程,並啓動,在其Runnable接口的run方法中通過handler發送消息,並打印出與該handler相關聯的looper所在的線程的名字。

打印結果如下:

ERROR/minrui(1630): main

結果似乎有點出人意料,但是仔細分析,啓動的名爲“malone”的線程並未與一個looper相關聯,並且handler中的looper是與主線程關聯的,結果確實應該是這樣。

那麼,可不可以在主線程中定義handler,在代碼中動態改變handler使之與其他線程的looper相關聯呢?看以下的例子:

mRunnable = new  Runnable(){

              @Override

              public void run() {

                  // TODO Auto-generated method stub

                  Looper.prepare();

                  mHandler = new Handler(Looper.myLooper());

                  String s = mHandler.getLooper().getThread().getName();

                  Log.e("minrui", s);

                  mHandler = new Handler(Looper.getMainLooper());

                   s = mHandler.getLooper().getThread().getName();

                  Log.e("minrui", s);        

              }};

    Thread t  = new Thread(mRunnable,"malone");

            t.start();

結果打印如下:

ERROR/minrui(4049): malone

ERROR/minrui(4049): main

Android提供了一個包含looperthread類,這個類的名字叫HandlerThread,我們看一下這個類的用法:

t = new HandlerThread("malone123");

        t .start();

        mHandler1 = new Handler(t.getLooper());

        mHandler1.post(new  Runnable(){

           @Override

           public void run() {

              // TODO Auto-generated method stub

              String s = mHandler1.getLooper().getThread().getName();

              Log.e("minrui", s);

           }

        });

打印結果如下:

ERROR/minrui(3528):  malone123

有一點值得注意的是:

android2.1之前,android認爲在非線程中操作UI界面是不安全的,因此禁止在其它線程中修改UI界面。解決的方法有兩種,一是通過在主線程中定義的handler更新界面,二是直接調用被修改的viewpostInvalidate方法刷新單個view

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章