標籤:android 非同步 子線程切換到主線程 genius handler
========================================================
qiujuer
部落格:blog.csdn.net/qiujuer
網站:www.qiujuer.net
開源庫:Genius-Android
轉載請註明出處:http://blog.csdn.net/qiujuer/article/details/41900879
========================================================
在 Android 的使用中經常會遇到從子線程切換到主線程進行介面更改的情況的;如果在一個Activity 中進行倒好說一個 Handler 即可解決問題;但是假如很多個介面呢?每個介面都建立一個Handler 嗎?太浪費了吧?咱們要的是簡潔;要的是效率!走起。。。。
本來打算在原來的文章 [Android] 任意時刻從子線程切換到主線程的實現 上面進行修改的;但是發現沒法啊;原來的那個出了些問題導致很難編輯,一編輯就亂的不成樣了;無奈新開了一章。我想應該與其中我複製了大量的有樣式的代碼有關。
在上一章 [Android] 任意時刻從子線程切換到主線程的實現 中介紹了其具體的實現方式;但是沒有系統的說一下原理;在這裡就敘說一下。
原理Handler原理:
當然其有很多細節部分沒有一一畫出來,這裡就先過去了;將就看看啊 哈哈。
ToolKit 一鍵操作原理:
這裡直接看或許會有些麻煩;一定要先看看上一章 [Android] 任意時刻從子線程切換到主線程的實現 中的內容後再看。不然這個圖片就是一個廢圖。
New
都說了要加入新的功能,是啥呢?在上一章中說了有一種同步方法;該方法將會等待主線程執行了子線程的任務後,子線程才返回。這種是屬於比較賴皮的形式。
假如子線程是女神,主線程是你;現在女神等你做事兒;但是呢你的人緣比較不錯有很多女神都把任務給你;而其中一個女神就不樂意了;她就想要是你慢慢的做,我還這麼等著你,豈不是太給你面子了。
然後女神就想,我等你半個小時吧;如果半個小時了你做了那我就接受你吧,如果沒有那就拜拜吧。
針對這樣的時間等待情況我們就需要加入一個新的方法: public static void runOnMainThreadSync(Runnable runnable, int waitTime, boolean cancel)。
原來的
public static void runOnMainThreadSync(Runnable runnable) :
public static void runOnMainThreadSync(Runnable runnable) { if (Looper.myLooper() == Looper.getMainLooper()) { runnable.run(); return; } SyncPost poster = new SyncPost(runnable); getMainPoster().sync(poster); poster.waitRun(); }現在我們建立一個新的方法,只需要在上面改動幾下。
新的 public static void runOnMainThreadSync(Runnable runnable, int waitTime, boolean cancel):
public static void runOnMainThreadSync(Runnable runnable, int waitTime, boolean cancel) { if (Looper.myLooper() == Looper.getMainLooper()) { runnable.run(); return; } SyncPost poster = new SyncPost(runnable); getMainPoster().sync(poster); poster.waitRun(waitTime, cancel); }可以看見其中多了兩個參數,一個是女神等待的時間:
waitTime ;第二個參數就是女神走了後 你究竟還做不做該女神下達的任務
(cancel)。
女神:子線程 飾
你:主線程 飾
當然對應的 SyncPost 中的 public void waitRun() 方法也需要新添加一個類似的方法,為瞭解釋就直接添加方法了,沒有在原來的方法上修改。
原來的:public void waitRun():
public void waitRun() { if (!end) { synchronized (this) { if (!end) { try { this.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } } } }新添加的:public void waitRun(int time, boolean cancel):
public void waitRun(int time, boolean cancel) { if (!end) { synchronized (this) { if (!end) { try { this.wait(time); } catch (InterruptedException e) { e.printStackTrace(); } finally { if (!end && cancel) end = true; } } } } }可以看見其中的
this.wait(time); 進行了時間等待。
同時在完成後我們根據情況改變了 END 變數的狀態。當然這裡改變了,那麼你做任務的時候就需要先判斷了。
所以原來的執行方法:public void run():
public void run() { synchronized (this) { runnable.run(); end = true; try { this.notifyAll(); } catch (Exception e) { e.printStackTrace(); } } }要更改為:
public void run() { if(!end) { synchronized (this) { if(!end) { runnable.run(); end = true; try { this.notifyAll(); } catch (Exception e) { e.printStackTrace(); } } } } }也就是在進入同步前與同步後分別進行判斷該狀態是否為Flase 。如果是則證明需要執行;那麼就進行執行。
代碼部分就OK了,大家可以測試測試!
情境
針對上面新加的功能有如下情境:前提(女神叫你做事情;最長等待時間半個小時!)
- 女神和你在一起,那麼立刻就做事情。(此時女神就是主線程的情況,實際工作折就是女神;也可以說是你;因為你也是主線程)
- 女神等了半個小時然後走了,至於之後你做不做女神給你的這個任務取決於女神的態度
- 女神還沒有等你就開始做了,此時女神壓根兒就不會想等待的事情;也就是說不會執行到 this.wait(time); 語句;因為擷取到同步塊後就退出了。她等待的時間是花在等待進入同步塊上。
- 女神已經開始等待了12分鐘了;此時你開始做了你在18分鐘內完成了;那麼說明是按時完成任務。
- 女神已經開始等待了12分鐘了;此時你開始做了,但是你還需要20分鐘完成,女神在你完成前走了;此時不管女神說叫你做還是不做你都會把它做完的;你是個有責任的男人。
總結
- cancel 變數只有在等待時間到了你卻還未執行的情況下才有效果。
- 任務一旦開始執行就不會中途退出,無論此時女神是否走了。
代碼:
ToolKit.java
HandlerPoster.java
SyncPost.java
========================================================
qiujuer
部落格:blog.csdn.net/qiujuer
網站:www.qiujuer.net
開源庫:Genius-Android
轉載請註明出處:http://blog.csdn.net/qiujuer/article/details/41900879
========================================================
[Android] 任意時刻從子線程切換到主線程的實現原理及加強版