Android 自定義線程管理器(串行)

本管理器優(yōu)點:
1.單頁面來說蝠筑,handlerThread作為主要管理方式物赶,一個線程復用,對性能影響小
2.簡化代碼较坛,一句代碼即可開啟一個異步任務印蔗,一句代碼把異步結(jié)果傳給UI線程
本管理器缺點:
1.由于單線程串行處理任務,有阻塞情況會影響其他任務丑勤。
2.每個activity一個管理器(一個線程)华嘹,當連續(xù)開啟多個activity的時候,同樣對性能影響較大法竞,有OOM風險耙厚。

以前寫項目的時候,都是直接new Thread()來創(chuàng)建線程岔霸,這樣寫項目后期非常不利于維護薛躬,然后考慮是否能寫一個類專門用來管理線程呢?

首先我們需要創(chuàng)建一個線程:

private HandlerThread mHandlerThread;
public void oncreate() {
    this.mHandlerThread = 
         new HandlerThread("activity worker:" + this.getClass().getSimpleName());
    this.mHandlerThread.start();
}

第二我們線程管理器只是管理線程呆细,不進行具體的邏輯操作型宝,那么就用到了Handler機制:

先創(chuàng)建一個UiHandler:

private static class UiHandler extends Handler {
    private  HandlerManager manager;
    public UiHandler(HandlerManager manager) {
        this.manager = manager;
    }

    public void handleMessage(Message msg) {
        super.handleMessage(msg);
        if(manager  != null) {
            //調(diào)用處理業(yè)務代碼
        }
    }
}

由于Handler為靜態(tài)內(nèi)部類,與外部類并無直接聯(lián)系,這樣處理容易產(chǎn)生內(nèi)存泄漏趴酣,manager對象無法釋放梨树,那么就要介入弱引用來處理該代碼(也可以用軟引用):

private static class UiHandler extends Handler {
    private  WeakReference<HandlerManager> mActivityReference;
    public UiHandler(HandlerManager manager) {
        this.mActivityReference = new WeakReference(manager);
    }

    public void handleMessage(Message msg) {
        super.handleMessage(msg);
        //調(diào)用處理業(yè)務代碼
        }

    }
}

同理還有創(chuàng)建一個異步線程BackgroundHandler,需要注意的是創(chuàng)建該Handler需要把新創(chuàng)建的線程looper傳遞過去:

private static class BackgroundHandler extends Handler {
    private  WeakReference<HandlerManager> mActivityReference;
    BackgroundHandler(HandlerManager manager, Looper looper) {
        super(looper);
        this.mActivityReference = new WeakReference(manager);
    }
    //發(fā)送消息
    public void handleMessage(Message msg) {
        super.handleMessage(msg);
        //調(diào)用處理業(yè)務代碼
        }

    }
}

這兩個Handler我們需要在線程創(chuàng)建的時候就創(chuàng)建岖寞,所以OnCreate方法要這樣改:

public void oncreate() {
    this.mHandlerThread = new HandlerThread("activity worker:" + this.getClass().getSimpleName());
    this.mHandlerThread.start();
    this.mBackgroundHandler 
            = new BackgroundHandler(this, this.mHandlerThread.getLooper());
    this.mUiHandler = new UiHandler(this);
}

第三我們就要發(fā)送消息了抡四,先理清邏輯:

1.通過消息通知Manager有異步請求。
2.Manager給BackgroundHandler發(fā)消息讓他處理異步邏輯仗谆。
3.BackgroundHandler處理異步邏輯指巡,并把處理結(jié)果返回給Manager。
4.Manager拿到處理結(jié)果發(fā)消息給UiHandler隶垮。
5.責任人(UiHandler)處理最后邏輯藻雪。

1.接收異步請求方法:

public void sendBackgroundMessage(int what, Object object) {
    Message message = this.obtainBackgroundMessage();
    message.what = what;
    message.obj = object;
    this.sendBackgroundMessage(message);
}
public Message obtainBackgroundMessage() 
    return this.mBackgroundHandler.obtainMessage();
}

2.發(fā)消息給BackGroundHandler:

public void sendBackgroundMessage(Message message) {
    this.mBackgroundHandler.sendMessage(message);
}

3.BackgroudHandler處理異步邏輯:

 private static class BackgroundHandler extends Handler {
    private  WeakReference<HandlerManager> mActivityReference;
    BackgroundHandler(HandlerManager manager, Looper looper) {
        super(looper);
        this.mActivityReference = new WeakReference(manager);
    }
    //發(fā)送消息
    public void handleMessage(Message msg) {
        super.handleMessage(msg);
        //如果引用不為空,發(fā)送消息
        if(this.mActivityReference.get() != null) {
 ((HandlerManager)this.mActivityReference.get()).handleBackgroundMessage(msg);
        }
    }
}
public abstract void handleBackgroundMessage(Message var1);

4.Manager拿到處理結(jié)果發(fā)消息給UiHandler:

public void sendUiMessage(int what, Object obj, long delay) {
    Message me = this.obtainUiMessage();
    me.what = what;
    me.obj = obj;
    this.sendUiMessage(me, delay);
}
public void sendUiMessage(Message message, long delay) {
    this.mUiHandler.sendMessageDelayed(message, delay);
}

5.UiHandler處理最后邏輯:

private static class UiHandler extends Handler {
    private  WeakReference<HandlerManager> mActivityReference;
    public UiHandler(HandlerManager manager) {
        this.mActivityReference = new WeakReference(manager);
    }
    public void handleMessage(Message msg) {
        super.handleMessage(msg);
        if(this.mActivityReference.get() != null) {
            ((HandlerManager)this.mActivityReference.get()).handleUiMessage(msg);
        }
    }
}
public abstract void handleUiMessage(Message var1);

最后附帶完整代碼:

public abstract class HandlerManager {
private HandlerThread mHandlerThread;//含有Looper的Thread
private BackgroundHandler mBackgroundHandler;//后臺接收消息的handler載體
private Handler mUiHandler;//主線程接收消息的handler載體

public HandlerManager() {
}
//給主線直接發(fā)送message對象
public void sendUiMessage(Message message) {
    this.mUiHandler.sendMessage(message);
}
//給主線程發(fā)送what和obj岁疼,自動組合成message對象
public void sendUiMessage(int what, Object object) {
    Message message = this.obtainUiMessage();
    message.what = what;
    message.obj = object;
    this.sendUiMessage(message);
}
//給主線程發(fā)送空消息
public void sendUiMessage(int what) {
    this.mUiHandler.sendEmptyMessage(what);
}
//給主線程發(fā)送延遲消息
public void sendUiMessage(int what, long delay) {
    this.mUiHandler.sendEmptyMessageDelayed(what, delay);
}
//給主線程發(fā)送what和obj阔涉,自動組合成message對象(帶延遲)
public void sendUiMessage(int what, Object obj, long delay) {
    Message me = this.obtainUiMessage();
    me.what = what;
    me.obj = obj;
    this.sendUiMessage(me, delay);
}
//給主線直接發(fā)送message對象(帶延遲)
public void sendUiMessage(Message message, long delay) {
    this.mUiHandler.sendMessageDelayed(message, delay);
}
//給后臺線程發(fā)送message對象(帶延遲)
public void sendBackgroundMessage(Message message, long delay) {
    this.mBackgroundHandler.sendMessageDelayed(message, delay);
}
//給后臺線程發(fā)送what和obj缆娃,自動組合成message對象(帶延遲)
public void sendBackgroundMessage(int what, Object object, long delay) {
    Message me = this.obtainBackgroundMessage();
    me.what = what;
    me.obj = object;
    this.sendBackgroundMessage(me, delay);
}

public Message obtainUiMessage() {
    return this.mUiHandler.obtainMessage();
}
//給后臺線程發(fā)送message對象
public void sendBackgroundMessage(Message message) {
    this.mBackgroundHandler.sendMessage(message);
}
//給后臺線程發(fā)送what和obj捷绒,自動組合成message對象
public void sendBackgroundMessage(int what, Object object) {
    Message message = this.obtainBackgroundMessage();
    message.what = what;
    message.obj = object;
    this.sendBackgroundMessage(message);
}
//給后臺線程發(fā)送空消息
public void sendBackgroundMessage(int what) {
    this.mBackgroundHandler.sendEmptyMessage(what);
}
//給主線程發(fā)送空消息(帶延遲)
public void sendBackgroundMessage(int what, long delay) {
    this.mBackgroundHandler.sendEmptyMessageDelayed(what, delay);
}

public Message obtainBackgroundMessage() {
    return this.mBackgroundHandler.obtainMessage();
}
//初始化handlermanager對象
public void oncreate() {
    this.mHandlerThread 
        = new HandlerThread("activity worker:" 
            + this.getClass().getSimpleName());
    this.mHandlerThread.start();
    this.mBackgroundHandler 
        = new BackgroundHandler(this, this.mHandlerThread.getLooper());
    this.mUiHandler = new UiHandler(this);
}
//清空HandlerManager對象中數(shù)據(jù),防止內(nèi)存泄漏
public void onDestroy() {
    if(this.mBackgroundHandler != null &&
        this.mBackgroundHandler.getLooper() != null) {
        this.mBackgroundHandler.getLooper().quit();
    }

}

public abstract void handleBackgroundMessage(Message var1);

public abstract void handleUiMessage(Message var1);
/**
 * UI線程
 * */
private static class UiHandler extends Handler {
    //HandlerManager 的弱引用贯要,防止內(nèi)存泄漏
    private  WeakReference<HandlerManager> mActivityReference;

    public UiHandler(HandlerManager manager) {
        this.mActivityReference = new WeakReference(manager);
    }

    public void handleMessage(Message msg) {
        super.handleMessage(msg);
        //如果引用不為空暖侨,發(fā)送消息
        if(this.mActivityReference.get() != null) {
            ((HandlerManager)this.mActivityReference.get())
                .handleUiMessage(msg);
        }

    }
}
/**
 * 后臺線程
 * */
private static class BackgroundHandler extends Handler {
    //HandlerManager 的弱引用,防止內(nèi)存泄漏
    private  WeakReference<HandlerManager> mActivityReference;

    BackgroundHandler(HandlerManager manager, Looper looper) {
        super(looper);
        this.mActivityReference = new WeakReference(manager);
    }
    //發(fā)送消息
    public void handleMessage(Message msg) {
        super.handleMessage(msg);
        //如果引用不為空崇渗,發(fā)送消息
        if(this.mActivityReference.get() != null) {
            ((HandlerManager)this.mActivityReference.get())
                  .handleBackgroundMessage(msg);
        }

    }
}

下面是調(diào)用代碼(建議寫在BaseActivity中):

private HandlerManager handlerManager;//線程管理器
private void initHandle() {
    this.handlerManager = new HandlerManager() {
        public void handleBackgroundMessage(Message message) {
            BaseActivity.this.handleBackgroundMessage(message);
        }

        public void handleUiMessage(Message message) {
            BaseActivity.this.handleUiMessage(message);
        }
    };
    this.handlerManager.oncreate();
}

 public void onDestroy() {
    super.onDestroy();
    this.handlerManager.onDestroy();
}

 @Override
public void sendUiMessage(Message var1) {
    handlerManager.sendUiMessage(var1);
}

@Override
public void sendUiMessage(int var1, Object var2) {
    handlerManager.sendUiMessage(var1, var2);
}

@Override
public void sendUiMessage(int var1) {
    handlerManager.sendUiMessage(var1);
}

@Override
public void sendUiMessage(int var1, long var2) {
    handlerManager.sendUiMessage(var1, var2);
}

@Override
public void sendUiMessage(int var1, Object var2, long var3) {
    handlerManager.sendUiMessage(var1, var2, var3);
}

@Override
public void sendUiMessage(Message var1, long var2) {
    handlerManager.sendUiMessage(var1, var2);
}

 @Override
public void sendBackgroundMessage(Message var1) {
    handlerManager.sendBackgroundMessage(var1);
}

@Override
public void sendBackgroundMessage(int var1, Object var2) {
    handlerManager.sendBackgroundMessage(var1,var2);
}

@Override
public void sendBackgroundMessage(int var1) {
    handlerManager.sendBackgroundMessage(var1);
}

@Override
public void sendBackgroundMessage(int var1, long var2) {
    handlerManager.sendBackgroundMessage(var1,var2);
}

@Override
public void sendBackgroundMessage(int var1, Object var2, long var3) {
    handlerManager.sendBackgroundMessage(var1,var2,var3);
}

@Override
public void sendBackgroundMessage(Message var1, long var2) {
    handlerManager.sendBackgroundMessage(var1,var2);
}

@Override
public void handleBackgroundMessage(Message var1) {
}

@Override
public void handleUiMessage(Message var1) {
}
二維碼.jpg

推薦下本人的微信公眾號字逗,本博客及其他方面的消息會定期同步到公眾號上面!

最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末宅广,一起剝皮案震驚了整個濱河市葫掉,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌跟狱,老刑警劉巖俭厚,帶你破解...
    沈念sama閱讀 216,692評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異驶臊,居然都是意外死亡挪挤,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,482評論 3 392
  • 文/潘曉璐 我一進店門关翎,熙熙樓的掌柜王于貴愁眉苦臉地迎上來扛门,“玉大人,你說我怎么就攤上這事纵寝÷壅” “怎么了?”我有些...
    開封第一講書人閱讀 162,995評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長葬凳。 經(jīng)常有香客問我贞铣,道長,這世上最難降的妖魔是什么沮明? 我笑而不...
    開封第一講書人閱讀 58,223評論 1 292
  • 正文 為了忘掉前任辕坝,我火速辦了婚禮,結(jié)果婚禮上荐健,老公的妹妹穿的比我還像新娘酱畅。我一直安慰自己,他們只是感情好江场,可當我...
    茶點故事閱讀 67,245評論 6 388
  • 文/花漫 我一把揭開白布纺酸。 她就那樣靜靜地躺著,像睡著了一般址否。 火紅的嫁衣襯著肌膚如雪餐蔬。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,208評論 1 299
  • 那天佑附,我揣著相機與錄音樊诺,去河邊找鬼。 笑死音同,一個胖子當著我的面吹牛词爬,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播权均,決...
    沈念sama閱讀 40,091評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼顿膨,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了叽赊?” 一聲冷哼從身側(cè)響起恋沃,我...
    開封第一講書人閱讀 38,929評論 0 274
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎必指,沒想到半個月后囊咏,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,346評論 1 311
  • 正文 獨居荒郊野嶺守林人離奇死亡取劫,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,570評論 2 333
  • 正文 我和宋清朗相戀三年匆笤,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片谱邪。...
    茶點故事閱讀 39,739評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡炮捧,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出惦银,到底是詐尸還是另有隱情咆课,我是刑警寧澤末誓,帶...
    沈念sama閱讀 35,437評論 5 344
  • 正文 年R本政府宣布,位于F島的核電站书蚪,受9級特大地震影響喇澡,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜殊校,卻給世界環(huán)境...
    茶點故事閱讀 41,037評論 3 326
  • 文/蒙蒙 一晴玖、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧为流,春花似錦呕屎、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,677評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至莲祸,卻和暖如春蹂安,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背锐帜。 一陣腳步聲響...
    開封第一講書人閱讀 32,833評論 1 269
  • 我被黑心中介騙來泰國打工田盈, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人抹估。 一個月前我還...
    沈念sama閱讀 47,760評論 2 369
  • 正文 我出身青樓缠黍,卻偏偏與公主長得像弄兜,于是被迫代替她去往敵國和親药蜻。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,647評論 2 354

推薦閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,082評論 25 707
  • 數(shù)著日子 一天一天就流轉(zhuǎn)到了開學之際 可是從放假以來有些渴望返回校園的我 再真正要踏入校園時 我思想360度大...
    猛擲閱讀 137評論 0 1
  • 生意的完整周期 =平均在庫天數(shù)+平均收現(xiàn)天數(shù) =應付賬款周轉(zhuǎn)天數(shù)+缺錢天數(shù) 上圖所示 缺錢天數(shù)=平均在庫天數(shù)+平均...
    至簡_f841閱讀 97評論 0 1
  • 我住在一座囚牢里蔚藍的天空空靈的水柔和的風和煦的陽光舒適的像條蟲子蠕蠕而動我卻害怕害怕這安逸的囚牢于是黑夜給我光明...
    淺海那妖魚閱讀 260評論 0 2
  • 游戲是大多女生都不愛替饿,大多男生都為之瘋狂的一種娛樂语泽,這是一個不爭的事實∈勇可是最近不少的女生都對游戲特別認真...
    靚穎雨露閱讀 302評論 3 2