基於觀察者模式android
感知生命週期git
自動解除數據訂閱github
UI和實時數據保持一致安全
不會發生內存泄露併發
不會再產生因爲Activity處於stop狀態而引發的崩潰app
不須要再解決生命週期帶來的問題ide
實時數據刷新函數
解決Configuration Change問題源碼分析
數據共享post
舉一個最簡單的案例代碼:
liveData = new MutableLiveData<>(); liveData.observe(this, new Observer<String>() { @Override public void onChanged(@Nullable final String newText) { // 更新數據 tv3.setText(newText); } }); liveData.setValue("小楊真的是一個逗比麼");
那麼上面這一段代碼大概是什麼意思呢?
LiveData是一個數據的包裝。具體的包裝對象能夠是任何數據,包括集合。它是一個抽象類,首先先建立一個類實現LiveData。代碼以下所示:
public class TextViewModel extends ViewModel { /**
*/ private MutableLiveData<String> mCurrentText; public MutableLiveData<String> getCurrentText() { if (mCurrentText == null) { mCurrentText = new MutableLiveData<>(); } return mCurrentText; } } ```
建立一個觀察的對象,觀察LiveData中的數據。目前在組件的onCreate()方法中開始觀察數據,代碼以下所示:
private void initLiveData() { // 建立一個持有某種數據類型的LiveData (一般是在ViewModel中) model = ViewModelProviders.of(this).get(TextViewModel.class); // 建立一個定義了onChange()方法的觀察者 // 開始訂閱 final Observer<String> nameObserver = new Observer<String>() { @Override public void onChanged(@Nullable final String newText) { // 更新數據 tvText.setText(newText); } }; // 經過 observe()方法鏈接觀察者和LiveData,注意:observe()方法須要攜帶一個LifecycleOwner類 model.getCurrentText().observe(this, nameObserver); }
而後去建立更新對象數據內容的對象。如何去更新那個文本中的數據呢?代碼以下所示:
findViewById(R.id.tv_click).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { count++; String text; switch (count%5){ case 1: text = "小楊真的是一個逗比麼"; break; case 2: text = "逗比趕忙來star吧"; break; case 3: text = "小楊想成爲大神"; break; case 4: text = "開始刷新數據啦"; break; default: text = "變化成默認的數據"; break; } model.getCurrentText().setValue(text); } });
通常咱們使用 LiveData 的 observe(),當數據更新後,LiveData 會通知它的全部活躍的觀察者。
直接查看源代碼,以下所示:
@MainThread public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<T> observer) { //當前綁定的組件(activity或者fragment)狀態爲DESTROYED的時候, 則會忽視當前的訂閱請求 if (owner.getLifecycle().getCurrentState() == DESTROYED) { // ignore return; } //建立生命週期感知的觀察者包裝類 LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer); //若是指定的鍵還沒有與某個值關聯,則將其與給定的值關聯 ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper); //對應觀察者只能與一個owner綁定 if (existing != null && !existing.isAttachedTo(owner)) { throw new IllegalArgumentException("Cannot add the same observer" + " with different lifecycles"); } if (existing != null) { return; } //lifecycle註冊 //添加一個LifecycleObserver,它將在LifecycleOwner更改狀態時獲得通知 owner.getLifecycle().addObserver(wrapper); }
而後看一下觀察者類LifecycleBoundObserver的源代碼
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) { // 當接收到 DESTROYED 的事件會自動解除跟 owner 的綁定 removeObserver(mObserver); return; } activeStateChanged(shouldBeActive()); } @Override boolean isAttachedTo(LifecycleOwner owner) { return mOwner == owner; } @Override void detachObserver() { mOwner.getLifecycle().removeObserver(this); } } //抽象類 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); } } } //接口 public interface GenericLifecycleObserver extends LifecycleObserver { /** * Called when a state transition event happens. * * @param source The source of the event * @param event The event */ void onStateChanged(LifecycleOwner source, Lifecycle.Event event); }
經過上面的代碼能夠發現什麼?
看一下ObserverWrapper抽象類中activeStateChanged方法中,onActive和onInactive分別幹什麼呢?
if (wasInactive && mActive) { onActive(); } if (LiveData.this.mActiveCount == 0 && !mActive) { onInactive(); }
看一下ObserverWrapper抽象類中activeStateChanged方法中,dispatchingValue是幹什麼呢?
關於observe源碼中這一行代碼ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper)做用是什麼呢?
//mObservers是一個集合 private SafeIterableMap<Observer<T>, ObserverWrapper> mObservers = new SafeIterableMap<>(); //在SafeIterableMap類中的putIfAbsent方法 public V putIfAbsent(@NonNull K key, @NonNull V v) { Entry<K, V> entry = get(key); if (entry != null) { return entry.mValue; } put(key, v); return null; } protected Entry<K, V> put(@NonNull K key, @NonNull V v) { Entry<K, V> newEntry = new Entry<>(key, v); mSize++; if (mEnd == null) { mStart = newEntry; mEnd = mStart; return newEntry; } mEnd.mNext = newEntry; newEntry.mPrevious = mEnd; mEnd = newEntry; return newEntry; }
那麼註冊觀察者以後的觸發流程是怎樣的?
LiveData 更新數據方式有兩個,一個是 setValue() 另外一個是 postValue(),這兩個方法的區別是,postValue() 在內部會拋到主線程去執行更新數據,所以適合在子線程中使用;而 setValue() 則是直接更新數據。
@MainThread protected void setValue(T value) { assertMainThread("setValue"); // 這裏的 mVersion,它本問題關鍵,每次更新數據都會自增,默認值是 -1。 mVersion++; mData = value; dispatchingValue(null); }
跟進下 dispatchingValue() 方法,注意,這裏須要重點看considerNotify代碼:
private void dispatchingValue(@Nullable ObserverWrapper initiator) { // mDispatchingValue的判斷主要是爲了解決併發調用dispatchingValue的狀況 // 當對應數據的觀察者在執行的過程當中, 若有新的數據變動, 則不會再次通知到觀察者。因此觀察者內的執行不該進行耗時工做 if (mDispatchingValue) { //給分發失敗打個標記 mDispatchInvalidated = true; return; } // 標記分發開始 mDispatchingValue = true; do { mDispatchInvalidated = false; //這裏須要注意:區分ObserverWrapper對象爲空,和不爲空的邏輯是不同的 if (initiator != null) { // 等下重點看這裏的代碼 considerNotify(initiator); initiator = null; } else { //能夠發現這裏用到mObservers集合,使用迭代器遍歷數據 for (Iterator<Map.Entry<Observer<T>, ObserverWrapper>> iterator = mObservers.iteratorWithAdditions(); iterator.hasNext(); ) { // 等下重點看這裏的代碼 considerNotify(iterator.next().getValue()); if (mDispatchInvalidated) { break; } } } } while (mDispatchInvalidated); // 標記分發開始 mDispatchingValue = false; }
接下來看一下上面源碼中initiator對象爲空判斷邏輯區別
而後看一下considerNotify() 方法作了什麼,代碼以下所示,這裏有道詞典翻譯下注釋
private void considerNotify(ObserverWrapper observer) { if (!observer.mActive) { return; } // 檢查最新的狀態b4調度。也許它改變了狀態,但咱們尚未獲得事件。 // 咱們仍是先檢查觀察者。活動,以保持它做爲活動的入口。 // 所以,即便觀察者移動到一個活動狀態,若是咱們沒有收到那個事件,咱們最好不要通知一個更可預測的通知順序。 if (!observer.shouldBeActive()) { observer.activeStateChanged(false); return; } //注意認真看下面的代碼 if (observer.mLastVersion >= mVersion) { return; } observer.mLastVersion = mVersion; //noinspection unchecked observer.mObserver.onChanged((T) mData); }
思考一下dispatchingValue除了setValue會調用,其餘還有地方調用麼?
private abstract class ObserverWrapper { final Observer<T> mObserver; boolean mActive; int mLastVersion = START_VERSION; //省略部分代碼 void activeStateChanged(boolean newActive) { if (newActive == mActive) { return; } // 當observer的狀態從active->inactive, 或者inactive->active的時候走如下流程 // 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(); } //當observer是從inactive->active的時候,須要通知到觀察者 if (mActive) { dispatchingValue(this); } } }
那麼發送消息事件以後的觸發流程是怎樣的?
這個方法是幹什麼用的呢?看一下源代碼
@MainThread public void observeForever(@NonNull Observer<T> observer) { // 建立一個AlwaysActiveObserver對象 AlwaysActiveObserver wrapper = new AlwaysActiveObserver(observer); ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper); if (existing != null && existing instanceof LiveData.LifecycleBoundObserver) { throw new IllegalArgumentException("Cannot add the same observer" + " with different lifecycles"); } if (existing != null) { return; } //刷新數據 wrapper.activeStateChanged(true); }