Android中優雅的線程切換寫法(一)

       最近我發現,項目中的Handler實例越來越多了,且非常的雜亂。甚至有的時候,只是爲了一個定時任務、延遲任務,便new了一個新的Handler實例。毫無疑問,這樣的寫法必然會導致最後的代碼冗餘極高,且極難維護。

       由此我想通過一個全局的Handler來實現優化,防止代碼冗餘。以下是我的做法。

       首先定義一個ThreadUtil類

public class ThreadUtil {
    //do something
}

     其次,在類中寫一個靜態方法:isRunMainThread()

public class ThreadUtil {
    /**
     * 用於判斷當前是否運行在主線程中
     */
    public static boolean isRunMainThread() {
        return Looper.getMainLooper() == Looper.myLooper();
    }
}

然後在該類中再定義一個Handler

public class ThreadUtil {

    /**
     * 這個Handler將會是整個項目中唯一的Handler實例
     */
    private static Handler handler = new Handler() {
        @Override
        public void dispatchMessage(Message msg) {
            super.dispatchMessage(msg);
            //do something
        }
    };

    /**
     * 用於判斷當前是否運行在主線程中
     */
    public static boolean isRunMainThread() {
        return Looper.getMainLooper() == Looper.myLooper();
    }
}

寫好這兩個基礎之後,我們就要開始對其進行拓展了。拓展的第一步是實現我們的基本需求:線程切換

一般情況下,我們可以通過View.post(Runnable run)、Handler.post(Runnable run)等方法,從子線程中跳轉至主線程來操作UI。

有時候也會通過new Thread(Runnable run).start()方法,從主線程跳轉至子線程來進行一些耗時操作,比如IO操作、網絡請求等。

基於這兩種需求,我們可以在ThreadUtil類中添加兩個方法:runOnMainThread、runOnChildThread

public class ThreadUtil {
    /.../

    /**
     * 將傳入的Runnable在主線程中運行起來
     */
    public static void runOnMainThread(Runnable runnable) {
        if (runnable == null) return;
        if (isRunMainThread()) {
            runnable.run();
        } else {
            handler.post(runnable);
        }
    }
    
    /**
     * 將傳入的Runnable在子線程中運行
     */
    public static void runOnChildThread(Runnable runnable) {
        if (runnable == null) return;
        if (isRunMainThread()) {
            new Thread(runnable).start();
        } else {
            runnable.run();
        }
    }
}

這兩個方法的原理都非常簡單。就是將需要執行的代碼塊,包裝在Runnable接口中,然後作爲參數傳入即可。

可是光是這樣不能算優雅,還可以繼續拓展,使這個類的功能更強大。

拓展第二步,延遲執行:

很多時候,我們並不希望Runnable中的代碼馬上執行,這是就需要延遲操作,那麼在我們這個類裏怎麼拓展呢?

public class ThreadUtil {
    
    private static final int DelayedRunChildThread = 1;

    /**
     * 這個Handler將會是整個項目中唯一的Handler實例
     */
    private static Handler handler = new Handler() {
        @Override
        public void dispatchMessage(Message msg) {
            super.dispatchMessage(msg);
            switch (msg.what) {
                case DelayedRunChildThread:
                    runOnChildThread((Runnable) msg.obj);
                    break;
            }
        }
    };

    /.../

    /**
     * 在主線程中延遲執行一個Runnable接口
     * @param time 延遲時間,以毫秒爲單位
     */
    public static void runOnMainThreadDelayed(Runnable runnable, long time) {
        if (runnable == null || time < 0) return;
        handler.postDelayed(runnable, time);
    }
    
    /**
     * 延遲執行一個子線程
     * @param time 延遲時間,以毫秒爲單位
     */
    public static void runOnChildThreadDelayed(Runnable runnable, long time) {
        if (runnable == null || time < 0) return;
        Message message = Message.obtain();
        message.what = DelayedRunChildThread;
        message.obj = runnable;
        handler.sendMessageDelayed(message, time);
    }

    
}

這裏我又添加了兩個方法:runOnMainThreadDelayed、runOnChildThreadDelayed。

如此一來,既可以在主線程中進行一些延遲操作,也可以在子線程中進行一些延遲操作。可這樣寫也帶來一些問題。

假設,某個代碼塊Runnable A延遲10秒執行,可到第7秒時,我想取消這個Runnable A怎麼辦?按照我們現在的寫法,似乎無法優雅的移除掉某個延遲的Runnable。

那麼我們再對ThreadUtil進行一次拓展,讓它具備移除Runnable任務的功能。傳送門->Android中優雅的線程切換寫法(二)

 

 

發佈了19 篇原創文章 · 獲贊 0 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章