LiveData的工做原理

前言

本篇文章主要講解LiveData工做的原理,若是還不知道LiveData如何用的話,請參考官方文檔。 LiveData的講解涉及到了Lifecycle的知識,若是你還不瞭解LifeCycle,請參考文檔LifeCycle介紹android

介紹

LiveData是一個數據持有類,它能夠經過添加觀察者被其餘組件觀察其變動。不一樣於普通的觀察者,它最重要的特性就是聽從應用程序的生命週期,如在Activity中若是數據更新了但Activity已是destroy狀態,LivaeData就不會通知Activity(observer)。固然。LiveData的優勢還有不少,如不會形成內存泄漏等。
數據庫

LiveData一般會配合ViewModel來使用,ViewModel負責觸發數據的更新,更新會通知到LiveData,而後LiveData再通知活躍狀態的觀察者。bash

原理分析

下面直接看代碼:網絡

public class UserProfileViewModel extends ViewModel {
    private String userId;
    private MutableLiveData<User> user;
    private UserRepository userRepo;

    public void init(String userId) {
        this.userId = userId;
        userRepo = new UserRepository();
        user = userRepo.getUser(userId);
    }

    public void refresh(String userId) {
        user = userRepo.getUser(userId);
    }

    public MutableLiveData<User> getUser() {
        return user;
    }

}
複製代碼

上面UserProfileViewModel內部持有 UserRepository 中 MutableLiveData的引用,而且提供了獲取 MutableLiveData 的方法 getUser(),UserRepository 負責從網絡或數據庫中獲取數據並封裝成 MutableLiveData 而後提供給 ViewModel。
app

咱們在 UserProfileFragment 中爲 MutableLiveData 註冊觀察者,以下:ide

@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
    super.onActivityCreated(savedInstanceState);
    String userId = getArguments().getString(UID_KEY);
    viewModel = ViewModelProviders.of(this).get(UserProfileViewModel.class);
    viewModel.init(userId);
    //標註1
    viewModel.getUser().observe(UserProfileFragment.this, new Observer<User>() {
        @Override
        public void onChanged(@Nullable User user) {
            if (user != null) {
                tvUser.setText(user.toString());
            }
        }
    });
}
複製代碼

看標註1處,viewModel.getUser()獲取到 MutableLiveData 也就是咱們的 LiveData,而後調用 LiveData的observer方法,並把UserProfileFragment做爲參數傳遞進去。observer() 方法就是咱們分析的入口了,接下來咱們看LiveData的observer()方法都作了什麼:post

@MainThread
public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<T> observer) {
    //標註1
    if (owner.getLifecycle().getCurrentState() == DESTROYED) {
        // ignore
        return;
    }
    //標註2
    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);
}
複製代碼

能夠看到,UserProfileFragment 是做爲 LifeCycleOwner 參數傳進來的,若是你的support包版本大於等於26.1.0,support包中的 Fragment 會默認繼承自 LifecycleOwner,而 LifecycleOwner 可獲取到該組件的 LifeCycle,也就知道了 UserProfileFragment 組件的生命週期(在這裏默認你們已經瞭解過LifeCycle了)。
看標註1處,若是咱們的 UserProfileFragment 組件已是destroy狀態的話,將直接返回,不會被加入觀察者行列。若是不是destroy狀態,就到標註2處,新建一個 LifecycleBoundObserver 將咱們的 LifecycleOwner 和 observer保存起來,而後調用 mObservers.putIfAbsent(observer, wrapper) 將observer和wrapper分別做爲key和value存入Map中,putIfAbsent()方法會判斷若是 value 已經可以存在,就返回,不然返回null。 若是返回existing爲null,說明之前沒有添加過這個觀察者,就將 LifecycleBoundObserver 做爲 owner 生命週期的觀察者,也就是做爲 UserProfileFragment 生命週期的觀察者。
咱們看下LifecycleBoundObserver 源碼:ui

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);
    }
}
複製代碼

代碼並很少,LifecycleBoundObserver 繼承自 ObserverWrapper 並實現了 GenericLifecycleObserver接口,而 GenericLifecycleObserver 接口又繼承自 LifecycleObserver 接口,那麼根據 Lifecycle 的特性,實現了LifecycleObserver接口而且加入 LifecycleOwner 的觀察者裏就能夠感知或主動獲取 LifecycleOwner 的狀態。
this

好了,看完了觀察者,那麼咱們的LiveData何時會通知觀察者呢?不用想,確定是數據更新的時候,而數據的更新是咱們代碼本身控制的,如請求網絡返回User信息後,咱們會主動將User放入MutableLiveData中,這裏我在UserRepository中直接模擬網絡請求以下:spa

public class UserRepository {
    final MutableLiveData<User> data = new MutableLiveData<>();

    public MutableLiveData<User> getUser(final String userId) {
        if ("xiasm".equals(userId)) {
            data.setValue(new User(userId, "夏勝明"));
        } else if ("123456".equals(userId)) {
            data.setValue(new User(userId, "哈哈哈"));
        } else {
            data.setValue(new User(userId, "unknow"));
        }
        return data;
    }
}
複製代碼

當調用getUser()方法的時候,咱們調用MutableLiveData的setValue()方法將數據放入LiveData中,這裏MutableLiveData實際上就是繼承自LiveData,沒有什麼特別:

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()在放入User的時候必須在主線程,不然會報錯,而postValue則沒有這個檢查,而是會把數據傳入到主線程。咱們直接看setValue()方法:

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

首先調用assertMainThread()檢查是否在主線程,接着將要更新的數據賦給mData,而後調用 dispatchingValue()方法並傳入null,將數據分發給各個觀察者,如咱們的 UserProfileFragment。看 dispatchingValue()方法實現:

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

從標註1能夠看出,dispatchingValue()參數傳null和不傳null的區別就是若是傳null將會通知全部的觀察者,反之僅僅通知傳入的觀察者。咱們直接看標註2,通知全部的觀察者經過遍歷 mObservers ,將全部的 ObserverWrapper 拿到,實際上就是咱們上面提到的 LifecycleBoundObserver,通知觀察者調用considerNotify()方法,這個方法就是通知的具體實現了。

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.mObserver就是咱們調用LiveData的observer()方法傳入的 Observer,而後調用 Observer 的 onChanged((T) mData)方法,將保存的數據mData傳入,也就實現了更新。在看下咱們實現的Observer:

viewModel.getUser().observe(UserProfileFragment.this, new Observer<User>() {
    @Override
    public void onChanged(@Nullable User user) {
        if (user != null) {
            tvUser.setText(user.toString());
        }
    }
});
複製代碼

若是哪一個控件要根據user的變動而及時更新,就在onChanged()方法裏處理就能夠了。到這裏,LiveData已經可以分析完了,其實LiveData的實現仍是要依賴於Lifecycle。

相關文章
相關標籤/搜索