liveData基本使用
class ChooseAreaViewModel :ViewModel(){
var provinceLiveData = MutableLiveData<MutableList<Province>>()
fun getProvinceList(){
viewModelScope.launch {
provinceLiveData.value = PlaceRepository.getProvinceList()
}
}
}
class MVVMActivity:AppCompatActivity() {
private lateinit var viewModel:ChooseAreaViewModel
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_mvvm)
viewModel = ViewModelProviders.of(this).get(ChooseAreaViewModel::class.java)
viewModel.provinceLiveData.observe(this, Observer {result->
Log.e("TAG",result[0].provinceName)
Log.e("TAG",Thread.currentThread().name)
text.text = result[0].provinceName+result[0].code+result[0].provinceCode
})
button.setOnClickListener {
viewModel.getProvinceList()
}
}
}
多个activity共享liveData
object LiveDataInstance {
val count = MutableLiveData<Int>()
fun setCount(data:Int){
count.value = data
}
}
class ChooseAreaViewModel :ViewModel(){
var count = LiveDataInstance.count
fun setCount(int: Int){
LiveDataInstance.setCount(int)
}
}
class ChooseAreaViewModel2 :ViewModel(){
var count = LiveDataInstance.count
fun setCount(int: Int){
LiveDataInstance.setCount(int)
}
}
class MVVMActivity:AppCompatActivity() {
private lateinit var viewModel:ChooseAreaViewModel
override fun onCreate(savedInstanceState: Bundle?) {
viewModel = ViewModelProviders.of(this).get(ChooseAreaViewModel::class.java)
viewModel.count.observe(this, Observer { result->
Log.e("TAG","$result")
text.text = "$result"
})
buttonCount.setOnClickListener {
viewModel.setCount(11111111)
}
}
}
class MVVMActivity2:AppCompatActivity() {
private lateinit var chooseAreaViewModel: ChooseAreaViewModel2
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_mvvm2)
chooseAreaViewModel = ViewModelProviders.of(this).get(ChooseAreaViewModel2::class.java)
chooseAreaViewModel.count.observe(this, Observer {result->
Log.e("TAG","$result")
tv.text = "$result"
})
button.setOnClickListener {
chooseAreaViewModel.setCount(22222)
}
}
}
源码分析
@MainThread
public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) {
........
LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer);
ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper);
........
owner.getLifecycle().addObserver(wrapper);
}
在注册时,首先把LifecycleOwner和Observer作为参数创建LifecycleBoundObserver对象,并把LifecycleBoundObserver作为键,LifecycleOwner作为值添加到mObservers这个SafeIterableMap中,然后获取lifeCycle,并且把LifecycleBoundObserver对象添加到lifeCycle中注册
接下来看
class LifecycleBoundObserver extends ObserverWrapper implements LifecycleEventObserver {
//lifeCycle当生命周期状态改变时回调,如果当前页面状态为DESTROYED,则移除Observer,否则都会调用activeStateChanged方法(该方法主要是粘性事件)
@Override
public void onStateChanged(@NonNull LifecycleOwner source,
@NonNull Lifecycle.Event event) {
if (mOwner.getLifecycle().getCurrentState() == DESTROYED) {
removeObserver(mObserver);
return;
}
activeStateChanged(shouldBeActive());
}
}
@MainThread
public void removeObserver(@NonNull final Observer<? super T> observer) {
.......
//从mObservers这个SafeIterableMap中移除
ObserverWrapper removed = mObservers.remove(observer);
.......
}
当lifeCycle回调的页面状态改变时,如果当前页面时DESTROYED状态,则移除Observer,否则不管页面生命周期处于哪种状态都会调用activeStateChanged方法,该方法用于处理粘性事件
void activeStateChanged(boolean newActive) {
........
if (mActive) {
dispatchingValue(this);
}
}
protected void setValue(T value) {
assertMainThread("setValue");
mVersion++;
mData = value;
dispatchingValue(null);
}
activeStateChanged方法和setValue方法(数据改变时)最终都会调用dispatchingValue
void dispatchingValue(@Nullable ObserverWrapper initiator) {
if (mDispatchingValue) {
mDispatchInvalidated = true;
return;
}
mDispatchingValue = true;
do {
mDispatchInvalidated = false;
//如果是生命周期改变调用的粘性事件直接调用considerNotify
if (initiator != null) {
considerNotify(initiator);
initiator = null;
} else {
//liveData值改变时,遍历所有的注册事件,调用considerNotify
for (Iterator<Map.Entry<Observer<? super T>, ObserverWrapper>> iterator =
mObservers.iteratorWithAdditions(); iterator.hasNext(); ) {
considerNotify(iterator.next().getValue());
if (mDispatchInvalidated) {
break;
}
}
}
} while (mDispatchInvalidated);
mDispatchingValue = false;
}
在dispatchingValue方法中首先判断是页面状态改变还是数据改变,如果是页面状态改变则直接调用considerNotify,如果是数据改变,则遍历liveData注册的每个Observer进行调用considerNotify,因此可以使用单例创建liveData实现多个activity页面的数据共享如例2
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;
observer.mObserver.onChanged((T) mData);
}
在considerNotify中注意mLastVersion,如果mLastVersion小于mVersion则直接进行方法回调,调用onChanged即通知页面数据修改
总结:在liveData中,使用观察者模式和lifeCycle,当页面状态改变时和liveData中的mData数据改变都会最终调用considerNotify进行通知页面数据改变,由于初始化时mLastVersion和mVersion值都为-1,故页面状态改变调用considerNotify后不会进行通知。而由于liveData中的调用setValue会导致mVersion++,故当先调用setValue后注册Observer在页面生命周期状态改变时依然会通知页面数据改变。而如果先注册Observer后调用setValue,则会遍历所有注册的Observer然后调用considerNotify,通知所有注册的页面数据更新