溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

LiveData源碼分析

發(fā)布時間:2020-05-30 00:51:05 來源:網(wǎng)絡(luò) 閱讀:1350 作者:sq5b964702d8b05 欄目:移動開發(fā)

前言

最近的項目重構(gòu)中加入LiveData框架,并且小碼的T-MVVM也是用了LiveData框架,好不好用你試試就知道(小碼口頭禪),對于LiveData使用的時候并未做太多的理解,于是乎翻了翻LiveData源代碼,在此做下筆記,

什么是LiveData
LiveData是一個數(shù)據(jù)持有類。它具有以下特點:

  • 數(shù)據(jù)可以被觀察者訂閱;
  • 能夠感知組件(Fragment、Activity、Service)的生命周期;
  • 只有在組件出于激活狀態(tài)才會通知觀察者有數(shù)據(jù)更新;

LiveData能為我們做什么

  • 能夠保證數(shù)據(jù)和UI統(tǒng)一,LiveData采用了觀察者模式,LiveData是被觀察者,當(dāng)數(shù)據(jù)有變化時會通知UI。
    • 減少內(nèi)存泄漏,LiveData能夠感知到組件的生命周期,當(dāng)組件處于DESTROYED狀態(tài)時,觀察者對象會被清除,當(dāng)Activity停止時不會導(dǎo)致Crash,因為組件處于非激活狀態(tài)時,不會收到LiveData中數(shù)據(jù)變化的通知。
    • 不需要額外的手動處理來響應(yīng)生命周期的變化,因為LiveData能夠感知組件的生命周期,所以就完全不需要在代碼中告訴LiveData組件的生命周期狀態(tài)。
    • 組件和數(shù)據(jù)相關(guān)的內(nèi)容能實時更新,組件在前臺的時候能夠?qū)崟r收到數(shù)據(jù)改變的通知,當(dāng)組件從后臺到前臺來時,LiveData能夠?qū)⒆钚碌臄?shù)據(jù)通知組件,因此保證了組件中和數(shù)據(jù)相關(guān)的內(nèi)容能夠?qū)崟r更新。
      若果橫豎屏切換(configuration change)時,不需要額外的處理來保存數(shù)據(jù),當(dāng)屏幕方向變化時,組件會被recreate,然而系統(tǒng)并不能保證你的數(shù)據(jù)能夠被恢復(fù)的。當(dāng)我們采用LiveData保存數(shù)據(jù)時,因為數(shù)據(jù)和組件分離了。當(dāng)組件被recreate,數(shù)據(jù)還是存在LiveData中,并不會被銷毀。
    • 資源共享.

接下來先從使用玩起,

  • 使用LiveData對象,
  • 繼承LiveData類,如MutableLiveData,
    發(fā)起數(shù)據(jù)通知2種方式:postValue和setValue:

             private MutableLiveData<String> mData=new MutableLiveData();
                mBookData.postValue("Hello LiveData");
                // mBookData.setValue("Hello LiveData");

此處postValue和setValue的區(qū)別,下文會提,
注冊觀察者并監(jiān)聽數(shù)據(jù)變化:

 mData.observe(this, new Observer<String>() {
        @Override
        public void onChanged(@Nullable String str) {
          Toast.makeText(this, str, Toast.LENGTH_SHORT).show();
        }
    });

使用非常簡單,僅此而已
通過observe方法注冊觀察者,哪咋們就看看observe里面具體干了什么,源代碼165行走起,

   //注冊觀察
 @MainThread
public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<T> observer) {

    if (owner.getLifecycle().getCurrentState() == DESTROYED) {
        // ignore
        return;
    }

    LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer);
    ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper);
    if (existing != null && !existing.isAttachedTo(owner)) {
        throw new IllegalArgumentException("Cannot add the same observer"
                + " with different lifecycles");
    }
    if (existing != null) {
        return;
    }
    owner.getLifecycle().addObserver(wrapper);
}

observe方法接收2個參數(shù),一個是具有生命周期的LifecycleOwner,另一個是觀察者Observer<T> ,首先判斷LifecycleOwner當(dāng)前的生命周期是否為Destroyed,如果是則直接 return;如果不等于Destroyed,接下來往下看, 此處new了一個內(nèi)部類LifecycleBoundObserver對象并且構(gòu)造方法傳入了具有生命周期的LifecycleOwner和觀察者,這是個什么鬼,看看他的具體方法,LifecycleBoundObserver繼承自O(shè)bserverWrapper,并實現(xiàn)GenericLifecycleObserver,而GenericLifecycleObserver繼承了LifecycleObserver接口。由此可以看出LifecycleBoundObserver類就是把Observer和生命周期關(guān)聯(lián)起來,ok,那我們先看看LifecycleBoundObserver方法,源代碼349行走起,

   class LifecycleBoundObserver extends ObserverWrapper implements GenericLifecycleObserver {
    @NonNull final LifecycleOwner mOwner;

    LifecycleBoundObserver(@NonNull LifecycleOwner owner, Observer<T> observer) {
        super(observer);
        mOwner = owner;
    }

    @Override
    boolean shouldBeActive() {
        return mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED);
    }

    @Override
    public void onStateChanged(LifecycleOwner source, Lifecycle.Event event) {
        if (mOwner.getLifecycle().getCurrentState() == DESTROYED) {
            removeObserver(mObserver);
            return;
        }
        activeStateChanged(shouldBeActive());
    }

    @Override
    boolean isAttachedTo(LifecycleOwner owner) {
        return mOwner == owner;
    }

    @Override
    void detachObserver() {
        mOwner.getLifecycle().removeObserver(this);
    }
}

此方法中,我們先看onStateChanged()方法,當(dāng)生命周期變化時會回調(diào),如果getCurrentState() == DESTROYED則removeObserver,反之則調(diào)用父類ObserverWrapper的activeStateChanged()方法,源代碼382行走起,

 private abstract class ObserverWrapper {
    final Observer<T> mObserver;
    boolean mActive;
    int mLastVersion = START_VERSION;

    ObserverWrapper(Observer<T> observer) {
        mObserver = observer;
    }

    abstract boolean shouldBeActive();

    boolean isAttachedTo(LifecycleOwner owner) {
        return false;
    }

    void detachObserver() {
    }

    void activeStateChanged(boolean newActive) {
        if (newActive == mActive) {
            return;
        }
        // immediately set active state, so we'd never dispatch anything to inactive
        // owner
        mActive = newActive;
        boolean wasInactive = LiveData.this.mActiveCount == 0;
        LiveData.this.mActiveCount += mActive ? 1 : -1;
        if (wasInactive && mActive) {
            onActive();
        }
        if (LiveData.this.mActiveCount == 0 && !mActive) {
            onInactive();
        }
        if (mActive) {
            dispatchingValue(this);
        }
    }
}

activeStateChanged()是干嘛的,首先判斷activeState新舊狀態(tài)是否相同,不同則把新的狀態(tài)賦給mActive,是生命周期狀態(tài)處于ACTIVE情況下的邏輯處理。如果新的狀態(tài)和舊的狀態(tài)相同則直接返回。這里有個常量LiveData.this.mActiveCount,看注釋可以理解為觀察者處于活動狀態(tài)
個數(shù),往下看 if (wasInactive && mActive)如果mActiveCount=0并且mActive為true,即觀察者處于活動狀態(tài)
個數(shù)從0變?yōu)?個則調(diào)用onActive(); 觀察者處于活動狀態(tài)
個數(shù)從1變?yōu)?時則調(diào)用onInactive()。然而onActive(),onInactive()并沒有任何實現(xiàn)代碼。好了,接下來繼續(xù)往下看dispatchingValue(this);應(yīng)該就是數(shù)據(jù)變化消息調(diào)度。源代碼112行走起,

  private void dispatchingValue(@Nullable ObserverWrapper initiator) {
    if (mDispatchingValue) {
        mDispatchInvalidated = true;
        return;
    }
    mDispatchingValue = true;
    do {
        mDispatchInvalidated = false;
        if (initiator != null) {
            considerNotify(initiator);
            initiator = null;
        } else {
            for (Iterator<Map.Entry<Observer<T>, ObserverWrapper>> iterator =
                    mObservers.iteratorWithAdditions(); iterator.hasNext(); ) {
                considerNotify(iterator.next().getValue());
                if (mDispatchInvalidated) {
                    break;
                }
            }
        }
    } while (mDispatchInvalidated);
    mDispatchingValue = false;
}

前面的幾行if 判斷姑且先不看,先看從if(initiator != null)開始看,如果initiator!= null調(diào)用considerNotify(initiator)方法;源代碼91行走起,

    private void considerNotify(ObserverWrapper observer) {
    if (!observer.mActive) {
        return;
    }
    // Check latest state b4 dispatch. Maybe it changed state but we didn't get the event yet.
    //
    // we still first check observer.active to keep it as the entrance for events. So even if
    // the observer moved to an active state, if we've not received that event, we better not
    // notify for a more predictable notification order.
    if (!observer.shouldBeActive()) {
        observer.activeStateChanged(false);
        return;
    }
    if (observer.mLastVersion >= mVersion) {
        return;
    }
    observer.mLastVersion = mVersion;
    //noinspection unchecked
    observer.mObserver.onChanged((T) mData);
}

看見沒有最后一行代碼 observer.mObserver.onChanged((T) mData); Observer的數(shù)據(jù)變化回調(diào);好了我們再回過頭看看initiator == null的邏輯,

   for (Iterator<Map.Entry<Observer<T>, ObserverWrapper>> iterator =
                    mObservers.iteratorWithAdditions(); iterator.hasNext(); ) {
                considerNotify(iterator.next().getValue());
                if (mDispatchInvalidated) {
                    break;
                }
            }

如果initiator == null 則會通過迭代器mObservers遍歷獲取ObserverWrapper,最終還是調(diào)用considerNotify方法;既然有取ObserverWrapper,咋們再看看在哪兒存的,在源碼171行:

  ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper);
    if (existing != null && !existing.isAttachedTo(owner)) {
        throw new IllegalArgumentException("Cannot add the same observer"
                + " with different lifecycles");
    }
    if (existing != null) {
        return;
    }
    owner.getLifecycle().addObserver(wrapper);

mObservers.putIfAbsent(observer, wrapper)存入容器中,mObservers.putIfAbsent這個添加數(shù)據(jù)的方式貌似很少見,于是乎在看看mObservers是個什么數(shù)據(jù)容器,成員變量中:

   private SafeIterableMap<Observer<T>, ObserverWrapper> mObservers =
        new SafeIterableMap<>();

這是個什么鬼,貌似以前很少見,查閱資料發(fā)現(xiàn):
SafeIterableMap有以下特性:
1;支持鍵值對存儲,用鏈表實現(xiàn),模擬成Map的接口
2:支持在遍歷的過程中刪除任意元素,不會觸發(fā)ConcurrentModifiedException
3:非線程安全
感興趣的可自行查閱,此處不再詳細(xì)介紹,
最后addObserver添加注冊。

下面在看看數(shù)據(jù)發(fā)起通知的邏輯,數(shù)據(jù)發(fā)起通知有2中方式:

  public class MutableLiveData<T> extends LiveData<T> {
    @Override
    public void postValue(T value) {
       super.postValue(value);
    }

   @Override
   public void setValue(T value) {
       super.setValue(value);
   }
 }

setValue和postValue2中方式,我們先看看setValue代碼:

@MainThread
protected void setValue(T value) {
    assertMainThread("setValue");
    mVersion++;
    mData = value;
    dispatchingValue(null);
}

private static void assertMainThread(String methodName) {
    if (!ArchTaskExecutor.getInstance().isMainThread()) {
        throw new IllegalStateException("Cannot invoke " + methodName + " on a background"
                + " thread");
    }
}

setValue第一行代碼 assertMainThread("setValue");則是判斷是否在主線程,所以貌似setValue方式必須在主線程中執(zhí)行,如果非主線程則拋出異常。
再看看postValue:

 protected void postValue(T value) {
    boolean postTask;
    synchronized (mDataLock) {
        postTask = mPendingData == NOT_SET;
        mPendingData = value;
    }
    if (!postTask) {
        return;
    }
    ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);
}

則postValue調(diào)用postToMainThread方法,最終還是用過setValue方式:

  private final Runnable mPostValueRunnable = new Runnable() {
    @Override
    public void run() {
        Object newValue;
        synchronized (mDataLock) {
            newValue = mPendingData;
            mPendingData = NOT_SET;
        }
        //noinspection unchecked
        setValue((T) newValue);
    }
};

因此最終明白為什么setValue方法只能在主線程中調(diào)用,postValue可以在任何線程中調(diào)用,如果是在后臺子線程中更新LiveData的值,必須調(diào)用postValue。

至此大概明白了LiveData是干嘛的 ,怎么干的,總的來說還是很好用的,于是乎就有個小小的想法,平時用Eventbus,RxBus什么的,貌似感覺LiveData也可以實現(xiàn)事件總線,既然有了想法,那就干唄,

/**
 * 事件總線
 *
 * @author:tqzhang on 18/9/11 17:22
 */
 public class LiveBus {

    private static volatile LiveBus instance;

    private final Map<Object, MutableLiveData<Object>> mLiveBus;

    private LiveBus() {
       mLiveBus = new HashMap<>();
    }

    public static LiveBus getDefault() {
        if (instance == null) {
            synchronized (LiveBus.class) {
               if (instance == null) {
                   instance = new LiveBus();
                }
            }
        }
       return instance;
   }

    /**
     *
     * subscriber 注冊時間 key
     */
   public <T> MutableLiveData<T> subscribe(Object subscriber, Class<T> tMutableLiveData) {
      checkNotNull(subscriber);
      checkNotNull(tMutableLiveData);
      if (!mLiveBus.containsKey(subscriber)) {
          mLiveBus.put(subscriber, new MutableLiveData<>());
      }
      return (MutableLiveData<T>) mLiveBus.get(subscriber);

  }
}

簡單的50行代碼實現(xiàn)類似Eventbus,RxBus的功能,小碼親測了,挺好使的。

 //發(fā)起通知
LiveBus.getDefault().subscribe("livedata",String.class).postValue("hello LiveData");

//注冊觀察
LiveBus.getDefault().subscribe("livedata",String.class).observe(this, new Observer<String>() {
        @Override
        public void onChanged(@Nullable String s) {
            Toast.makeText(activity, s, Toast.LENGTH_SHORT).show();
        }
    });
向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI