对于开发者而言,Android arch 中Lifecycle组件基本技能要求:掌握 ViewModel , LiveData.
同时需要了解与生命周期相关类:Lifecycle, LifecycleOwner,LifecycleObserver.
1)ViewModel 用法
package com.bradyxiao.android.mvvm;
import androidx.lifecycle.LiveData;
import androidx.lifecycle.MutableLiveData;
import androidx.lifecycle.ViewModel;
// extends ViewMode ,并添加数据处理方法,引入LiveData
public class UserViewModel extends ViewModel {
private MutableLiveData<User> data = new MutableLiveData<>();
public LiveData<User> asLiveData(){
return data;
}
public void doAction(User user){
if(user != null){
data.setValue(user);
}
}
@Override
protected void onCleared() {
super.onCleared();
//clear resource
}
}
package com.bradyxiao.android.mvvm;
import androidx.appcompat.app.AppCompatActivity;
import androidx.lifecycle.LiveData;
import androidx.lifecycle.Observer;
import androidx.lifecycle.ViewModelProviders;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import com.bradyxiao.android.R;
public class UserActivity extends AppCompatActivity {
private UserViewModel userViewModel;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_user);
Button changeBtn = findViewById(R.id.change_id);
final TextView nameText = findViewById(R.id.name_id);
//初始化ViewModel
userViewModel = ViewModelProviders.of(this).get(UserViewModel.class);
//bind data
final LiveData<User> userLiveData = userViewModel.asLiveData();
//observer data change
userLiveData.observe(this, new Observer<User>() {
@Override
public void onChanged(User user) {
if(user == null)return;
nameText.setText(user.toString());
}
});
changeBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
User user = new User();
user.name = "OnClick";
user.id = System.currentTimeMillis() / 1000;
userViewModel.doAction(user);
}
});
}
}
2) ViewModel 生命周期
ViewModel 与Activity(或Fragment)生命周期的关系
因此,同一个Activity 通过get 到的ViewModel是同一个对象。内部存储ViewModel的 ViewModelStore其实是一个Mapj结构, key是当前ViewModel类名。且 若是当前Activity finish时,会清空ViewModelStore的Map,即ViewModel被清除了,因此,ViewModel不会引起内存泄漏问题。
/**
* Destroy all fragments.
*/
@Override
protected void onDestroy() {
super.onDestroy();
if (mViewModelStore != null && !isChangingConfigurations()) {
mViewModelStore.clear();
}
mFragments.dispatchDestroy();
}
/**
* Clears internal storage and notifies ViewModels that they are no longer used.
*/
public final void clear() {
for (ViewModel vm : mMap.values()) {
vm.clear();
}
mMap.clear();
}
tips: 一般不要在ViewModel中引用Activity或Fragment。若是需要Context,可以使用Application,或者直接参考AndroidViewModel。
3)LiveData,主要涉及LifecycleOwner, LifecycleObsever, MutableLivaData,MediatorLivaData
//无初始化值
private MutableLiveData<User> data = new MutableLiveData<>();
//给定一个初始化值
private MutableLiveData<User> data = new MutableLiveData<>(new User());
//注入LifecycleOwner 和 LifecycleObserver
data.observe(UserActivity.this, new Observer<User>() {
@Override
public void onChanged(User user) {
});
4) LiveData 数据和LifecycleOwner生命周期变化关联
//注入观察者和LifecycleOwner
public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) {
assertMainThread("observe");
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); //绑定LifecycleOwner 和 LifecycleObserver,从而观察Owner周期状态的该变
}
//生命周期状态改变
触发LifecycleBoundObserver的onStateChanged方法
public void onStateChanged(@NonNull LifecycleOwner source,
@NonNull Lifecycle.Event event) {
if (mOwner.getLifecycle().getCurrentState() == DESTROYED) {
removeObserver(mObserver);
return;
}
activeStateChanged(shouldBeActive());
}
//activeStateChanged方法
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);
} }
}
//数据的分发
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);
}
//数据的分发
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<? super T>, ObserverWrapper>> iterator =
mObservers.iteratorWithAdditions(); iterator.hasNext(); ) {
considerNotify(iterator.next().getValue());
if (mDispatchInvalidated) {
break;
}
}
}
} while (mDispatchInvalidated);
mDispatchingValue = false;
}
tips: LiveData中数据分发除了生命周期状态的改变,还有一个非常重要的变量即 data对应的version. 每次数据的更新都伴随着version的改变及 version++;
5)LiveData 与ViewModel结合
LiveData 内部保存了LifecycleOwner 和 LifecycleObserver,也是一个Map结构。当LifecycleOwner 处于Destory state时,则lifecycleObserver调用 LiveData的remove(LifecycleObserver)方法清除Map中保留的LifecycleOwner 和 LifecycleObserve对;而且同时会将LifecycleOwner 和 LifecycleObserver解绑。这样就达到了 livedata中不存在LifecycleOwner的引用,及liveData不会引起LifecycleOwner泄露问题。
然而,为了针对与因此配置发生了改变而导致Activity重建的情况,以及希望此过程中LiveData能够保留,则和ViewModel结合可以解决这个问题,及在ViewModel中创建LiveData,及 liveData能够和ViewModel的生命周期保持一致;同时能够满足因配置改变发生Activity重建 ,而不会丢数据的情况。因为LiveData的对象还保存在ViewModel中。