WeakHandler繼續(xù)優(yōu)化

將Handler改成WeakHandler弱引用持有Context以后,新的問題來了,做了延遲操作以后關(guān)閉Activity,作為嚴謹?shù)模◤娖劝Y)程序猿,我們還是應(yīng)該手動去清除handler可能執(zhí)行的延遲任務(wù)Message。有沒有辦法每次頁面生命周期OnPause或者OnDestory的時候自動幫我們完成這個清理呢?這個時候Lifecycle這樣的好東西就能幫我們實現(xiàn)這個愿望了!

//重點1:首先記得把WeakHandler繼承LifecycleObserver ,這樣我們就能觀察引用的生命周期了
public class WeakHandler<T extends WeakHandler.WeakHandlerCallBack> extends Handler implements LifecycleObserver {

  //新增一個記錄我們發(fā)送消息的容器用于回收可能存在的延遲任務(wù)
  private Set<Integer> msgList = new HashSet<>();

  public WeakHandler(T t) {
        this.weakReference = new WeakReference<>(t);
        //重點2:在這里設(shè)置生命周期觀察
        if(weakReference.get() != null && weakReference.get() instanceof LifecycleOwner){
            ((LifecycleOwner) weakReference.get()).getLifecycle().addObserver(this);
        }
    }
  
    /**重點3:通過源碼我們發(fā)現(xiàn),所有sendMessage,以及Post任務(wù)最終都是通過這個函數(shù)發(fā)出去的,
      *我們重寫這個函數(shù)即可記錄所有參與發(fā)送的延遲任務(wù)(為了安全起見,
      *我們把所有發(fā)送過得任務(wù)都記錄下來)
    */
    @Override
    public boolean sendMessageAtTime(Message msg, long uptimeMillis) {
        /**實際開發(fā)中,如果你的項目頁面發(fā)射的數(shù)據(jù)比較多(個人感覺不會太多,所有記錄了全部數(shù)據(jù)),
          *可以加上uptimeMillis>0這個過濾條件,另外Post掉的Runner消息也可以采用一樣
          *的手段在這里記錄,然后再后續(xù)移除里進行Remove操作,我就不寫了*/
        if(msg != null){
            msgList.add(msg.what);
        }
        return super.sendMessageAtTime(msg, uptimeMillis);
    }

   /**重點4:注冊生命周期ON_STOP觀察者
      *這樣在我們的引用頁面調(diào)用OnStop的時候我們就能收到信息做remove處理了,很簡單吧!
      *同理,有些頁面我們不想在OnStop處理,而是需要在OnDestory處理,
      *那我們只需要注冊O(shè)N_DESTORY然后進行對應(yīng)的處理就可以了
    */
    @OnLifecycleEvent(Lifecycle.Event.ON_STOP)
    public void onStop(@NotNull LifecycleOwner owner){
        LogW.i("WeakHandler LifecycleOwner["+owner+"] onStop");
        cleanMsgQuee();
    }

    //這里也能處理Post任務(wù),自行參考這個就可以搞定了
    public synchronized void cleanMsgQuee(){
        if(msgList != null && msgList.size() > 0){
            Iterator<Integer> iterator = msgList.iterator();
            while (iterator.hasNext()) {
                Integer what = iterator.next();
                if(what != null){
                    removeMessages(what);
                    iterator.remove();
                }
                LogW.i("--->>> cleanMsgQuee remove:"+what);
            }
        }
    }
}

整個實現(xiàn)是不是賊簡單,hmm,這下可以直接無腦初始化以后調(diào)用了,再也不用擔(dān)心忘記回收Message的問題了!其實這里面還有可以優(yōu)化的地方,比如重復(fù)發(fā)送信息如何記錄,以及已經(jīng)完成的任務(wù)應(yīng)該及時去掉,我這里主要提供一個思路,要是有興趣的可以深入優(yōu)化一下!

Back:簡單好用的解決Handler持有引用導(dǎo)致內(nèi)存泄漏的方法
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容