[Android] 任意時刻從子線程切換到主線程的實現原理及加強版

========================================================
作者: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
========================================================

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