欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

花樣使用Handler與源碼分析

 更新時間:2019年01月14日 14:32:50   作者:Zy_JiBai  
今天小編就為大家分享一篇關(guān)于花樣使用Handler與源碼分析,小編覺得內(nèi)容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧

前幾天在跟公司大佬討論一個問題時,看到他使用Handler的一種方式,旁邊的同事在說:以前不是這么用的啊。這個問題引發(fā)了我的好奇,雖然當時翻清楚道理了,但是還是想給大家分享一下。

Handler在之前也說到過他的使用以及源碼分析,而且相信大家都知道如何使用它,最常見的使用方法恐怕就是下面這種了:

Handler handler = new Handler(){
  @Override
  public void handleMessage(Message msg) {
    super.handleMessage(msg);
  }
};

這種情況會有一個問題:我們都知道Handler是可以用在子線程給主線程更新的,當子線程給主線程回調(diào)時,主線程中的Handler通過接收發(fā)送過來的對應(yīng)消息,去執(zhí)行對應(yīng)的任務(wù)。而對于上面這個Handler對象,如果他是主線程中的,那么我們子線程中需要拿到主線程的這個Handler對象。

  final Handler handler = new Handler(){
    @Override
    public void handleMessage(Message msg) {
      super.handleMessage(msg);
    }
  };
  new Thread(new Runnable() {
    @Override
    public void run() {
      handler.sendMessage(new Message());
    }
  }).start();

但是上面這種寫法實在是太不好看了,而且handler還是一個局部變量,在其他方法中也無法使用。

  Handler handler;
  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    Log.e(TAG, "onCreate: " );
    handler = new Handler(){
      @Override
      public void handleMessage(Message msg) {
        super.handleMessage(msg);
      }
    };
    new Thread(new Runnable() {
      @Override
      public void run() {
        handler.sendMessage(new Message());
      }
    }).start();
  }

這個看上去應(yīng)該就好多了,可能也是大多數(shù)人的一種寫法。

其實說白了,如果說我們要在子線程中給主線程/相應(yīng)線程回調(diào),那么一定要拿到主線程中的Handler的索引。這么說就很直接了,可能有些情況下無法拿到主線程/相應(yīng)線程的Handler,或者拿到的方法很麻煩:

public class MyService extends Service {
  @Nullable
  @Override
  public IBinder onBind(Intent intent) {
    return null;
  }
  @Override
  public void onCreate() {
    super.onCreate();
    new Thread(new Runnable() {
      @Override
      public void run() {
        //執(zhí)行相關(guān)的耗時操作,然后結(jié)束后通過Handler回調(diào)給主線程
      }
    }).start();
  }
}

現(xiàn)在我有這樣的需求:創(chuàng)建一個服務(wù),在服務(wù)中開啟一個子線程執(zhí)行耗時操作,當執(zhí)行完畢后回調(diào)在主線程中相應(yīng)。這種情況下想要拿到主線程的Handler對象也不是不可以,方法還是有很多,把主線程的handler寫成static、創(chuàng)建類繼承Handler并且序列化,然后通過intent傳入.....可能還有其他的一些方法,但是就目前的這些情況來看,貌似都不是很友好。下面給大家?guī)硪环N比較優(yōu)雅且方便的方法:

public class MyService extends Service {
  @Nullable
  @Override
  public IBinder onBind(Intent intent) {
    return null;
  }
  @Override
  public void onCreate() {
    super.onCreate();
    new Thread(new Runnable() {
      @Override
      public void run() {
        /*執(zhí)行相關(guān)的耗時操作,然后結(jié)束后通過Handler回調(diào)給主線程*/
        new Handler(Looper.getMainLooper()).sendMessage(new Message());
      }
    }).start();
  }
}

只有一句話:又方便看著又舒服。

(可能有的朋友不知道Looper是什么,本人之前寫過一篇Handler的文章對Looper有所介紹,希望對大家有所幫助:http://www.dbjr.com.cn/article/55386.htm

通過Looper.getMainLooper方法,可以獲取到主線程的Looper對象.

雖然之前說我們需要主線程中創(chuàng)建的Handler,其實嚴格的說是不對的。究其根本是因為主線程已經(jīng)為他自己加載了mainLooper,而我們在主線程中new Handler,會默認獲取主線程的Looper引用。

  public static void main(String[] args) {
    //pass
    Looper.prepareMainLooper();
    //pass
    Looper.loop();
    throw new RuntimeException("Main thread loop unexpectedly exited");
  }
  public Handler(Callback callback, boolean async) {
    //pass
    mLooper = Looper.myLooper();//在主線程中new的Handler獲取到的looper就是主線程的mainLooper
    if (mLooper == null) {
      throw new RuntimeException(
        "Can't create handler inside thread that has not called Looper.prepare()");
    }
    //pass
  }

現(xiàn)在看來就很明確了,在主線程中創(chuàng)建Handler只是個幌子,真正在背后操縱一切的其實是looper對象。所以只需要讓Handler的mLooper引用獲取到主線程的引用就好了。

而且Looper.getMainLooper方法是外部可見的,大膽猜測這個方法就是為了這種方便的寫法而存在的。我們可以通過這個方法獲取到主線程的looper,讓他實現(xiàn)主線程中接收回調(diào)。

  public Handler(Looper looper, Callback callback, boolean async) {
    mLooper = looper;
    mQueue = looper.mQueue;
    mCallback = callback;
    mAsynchronous = async;
  }

但是注意我們上述的這種寫法:new Handler(....).sendMessage

這種寫法不管你怎么去實現(xiàn),他無法在主線程得到回應(yīng)(是給大家挖了個坑哈哈),原因很簡單:沒有重寫Handler.handlerMessage方法。

在使用Handler接受消息時有三種方式:

  • 重寫Handler.handlerMessage方法,在該方法中接收
  • 在Handler構(gòu)造器中實現(xiàn)Callback接口,在回調(diào)接口中接收
  • 不做任何處理,但是使用post方式發(fā)送消息。

在之前我們Handler接收消息見到的幾乎都是handleMessage方法,其實這只是其中一種方法,在執(zhí)行該方法之前會有一個分發(fā)的方法dispatchMessage:

  /**
   * Handle system messages here.
   **/
  public void dispatchMessage(Message msg) {
    if (msg.callback != null) {//msg中的callback,這個是通過post方法自己封裝的msg(自行查源碼),優(yōu)先級是最高的
      handleCallback(msg);
    } else {//或者在構(gòu)造器中實現(xiàn)Handler的Callback接口,這個優(yōu)先級第二
      if (mCallback != null) {
        if (mCallback.handleMessage(msg)) {
          return;
        }
      }
      handleMessage(msg);//這才是我們之前最常用的方法,最低的優(yōu)先級
    }
  }

可以看到在handlerMessage方法之前還有兩種回調(diào)的方法。在上述案例中我們并沒有重寫第三種方法,所以對于在子線程中匿名使用Handler的情況,我們可以采取上述兩種方案。代碼就不寫了,大家都是聰明人。

好了關(guān)于Handler 的更多使用就到這里了,喜歡的朋友希望多多支持。有不同意見和理解的希望評論區(qū)多多交流。

總結(jié)

以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對大家的學習或者工作具有一定的參考學習價值,謝謝大家對腳本之家的支持。如果你想了解更多相關(guān)內(nèi)容請查看下面相關(guān)鏈接

相關(guān)文章

最新評論