麻豆小视频在线观看_中文黄色一级片_久久久成人精品_成片免费观看视频大全_午夜精品久久久久久久99热浪潮_成人一区二区三区四区

首頁 > 系統 > Android > 正文

花樣使用Handler與源碼分析

2019-10-21 21:30:17
字體:
來源:轉載
供稿:網友

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

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

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

這種情況會有一個問題:我們都知道Handler是可以用在子線程給主線程更新的,當子線程給主線程回調時,主線程中的Handler通過接收發送過來的對應消息,去執行對應的任務。而對于上面這個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();  }

這個看上去應該就好多了,可能也是大多數人的一種寫法。

其實說白了,如果說我們要在子線程中給主線程/相應線程回調,那么一定要拿到主線程中的Handler的索引。這么說就很直接了,可能有些情況下無法拿到主線程/相應線程的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() {        //執行相關的耗時操作,然后結束后通過Handler回調給主線程      }    }).start();  }}

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

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() {        /*執行相關的耗時操作,然后結束后通過Handler回調給主線程*/        new Handler(Looper.getMainLooper()).sendMessage(new Message());      }    }).start();  }}

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

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

雖然之前說我們需要主線程中創建的Handler,其實嚴格的說是不對的。究其根本是因為主線程已經為他自己加載了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  }

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

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

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

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

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

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

  • 重寫Handler.handlerMessage方法,在該方法中接收
  • 在Handler構造器中實現Callback接口,在回調接口中接收
  • 不做任何處理,但是使用post方式發送消息。

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

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

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

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

總結

以上就是這篇文章的全部內容了,希望本文的內容對大家的學習或者工作具有一定的參考學習價值,謝謝大家對VEVB武林網的支持.


注:相關教程知識閱讀請移步到Android開發頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 91精品国产91久久久 | 久久精品国产99国产精品澳门 | 男女羞羞的视频 | 中文字幕在线视频日本 | 精品国产一区二区三 | 毛片一区二区三区四区 | 日韩精品久久久 | 亚洲午夜电影 | 久久成人国产精品 | 成人勉费视频 | 99精品视频在线 | 全黄裸片武则天一级第4季 九色p | 黄色视屏免费看 | 欧美精品一区二区久久久 | a级高清免费毛片av在线 | 成人福利在线免费观看 | 羞羞的视频在线观看 | 国产激情精品一区二区三区 | 亚洲欧美国产精品va在线观看 | 欧美日韩亚洲精品一区二区三区 | 亚洲成人夜色 | 男人天堂免费 | 久久免费视屏 | 久久精品色 | 国产1区2区3区在线观看 | 一级免费看片 | 国产91在线亚洲 | 97人操 | 免费午夜视频在线观看 | 久久成人精品视频 | 369看片你懂的小视频在线观看 | 99视频在线观看视频 | 激情综合婷婷久久 | 成人免费影院 | 成人青青草 | 午夜视频在线免费观看 | chinesehdxxxx无套 久久另类视频 | 做爰裸体激情2 | 一级电影在线观看 | 在线播放视频一区二区 | 国产精品白嫩白嫩大学美女 |