========================================================
作者: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 變量只有在等待時間到了你卻還未執行的情況下才有效果。
- 任務一旦開始執行就不會中途退出,無論此時女神是否走了。
代碼:
UIKit.java
UIKitHandlerPoster.java
UIKitSyncPost.java
========================================================
作者:qiujuer
博客:blog.csdn.net/qiujuer
網站:www.qiujuer.net
開源庫:Genius-Android
轉載請註明出處:http://blog.csdn.net/qiujuer/article/details/41900879
========================================================