原文Android业务架构 · 基础篇 · Jetpack四件套 - 掘金 (juejin.cn)
一、Lifecycle
在最近的更新中,不建议直接使用LifecycleObserver,之前可以直接使用此接口,定义一个类去实现它,然后写几个方法,并使用 @OnLifecycleEvent 注解标注该方法在哪一个生命周期使用
@OnLifecycleEvent(Lifecycle.Event.ON_START)
private fun stopTimer() {
handler?.removeCallbacksAndMessages(null)
handler = null
}
推荐使用 LifecycleEventObserver或者DefaultLifecycleObserver
/**
* Marks a class as a LifecycleObserver. Don't use this interface directly. Instead implement either
* {@link DefaultLifecycleObserver} or {@link LifecycleEventObserver} to be notified about
* lifecycle events.
*
* @see Lifecycle Lifecycle - for samples and usage patterns.
*/
@SuppressWarnings("WeakerAccess")
public interface LifecycleObserver {
}
使用LifecycleEventObserver
class Timer : LifecycleEventObserver {
private var handler: Handler? = null
private var seconds = 0
private val TAG = "Timer"
private fun startTimer() {
handler = Handler(Looper.myLooper()!!)
handler?.post(object : Runnable {
override fun run() {
Log.d(TAG, "Seconds: $seconds")
seconds++
handler?.postDelayed(this, 1000)
}
})
}
private fun stopTimer() {
handler?.removeCallbacksAndMessages(null)
handler = null
}
override fun onStateChanged(source: LifecycleOwner, event: Lifecycle.Event) {
when (event) {
Lifecycle.Event.ON_START -> startTimer()
Lifecycle.Event.ON_STOP -> stopTimer()
else -> {}
}
}
}
主要重写 onStateChanged 方法,比如 ON_STAT,对应的就是activity或者fragment的create。
使用 DefaultLifecycleObserver
实现DefaultLifecycleObserver接口,根据需要去重写onCreate等方法即可。
最后在activity中注册
//添加observer
lifecycle.addObserver(Timer())
Lifecycle如何与Activity、Fragment关联起来的
核心主要是LifecycleOwner、LifecycleRegistry、Lifecycle、LifecycleObserver。
Lifecycle
抽象类,主要定义了一些用于标识生命的状态和事件。
//添加观察者
@MainThread
public abstract void addObserver(@NonNull LifecycleObserver observer);
//移除观察者
@MainThread
public abstract void removeObserver(@NonNull LifecycleObserver observer);
//获取当前状态
public abstract State getCurrentState();
//生命周期事件,对应Activity生命周期方法
public enum Event {
ON_CREATE,
ON_START,
ON_RESUME,
ON_PAUSE,
ON_STOP,
ON_DESTROY,
ON_ANY //可以响应任意一个事件`
}
//生命周期状态. (Event是进入这种状态的事件)
public enum State {
DESTROYED,
INITIALIZED,
CREATED,
STARTED,
RESUMED;
//判断至少是某一状态
public boolean isAtLeast(@NonNull State state) {
return compareTo(state) >= 0;
}
}
LifecycleRegistry继承Lifecycle,构造方法有以下几个。
public LifecycleRegistry(@NonNull LifecycleOwner provider) {
this(provider, true);
}
private LifecycleRegistry(@NonNull LifecycleOwner provider, boolean enforceMainThread) {
mLifecycleOwner = new WeakReference<>(provider);
mState = INITIALIZED;
mEnforceMainThread = enforceMainThread;
}
都会传入一个LifecycleOwner,就是生命周期持有者,一般是activity或者fragment,它们都会实现LifecycleOwner接口,重写getLifecycle方法,重写的方法都会返回一个LifecycleRegistry实例。
public interface LifecycleOwner {
@NonNull
Lifecycle getLifecycle();
}
- 对于fragment,直接在Fragment类中实现此接口。
- 对于Activity,它的继承关系主要由
AppCompatActivity->FragmentActivity->ComponentActivity,在ComponentActivity中实现此接口。
即activity和fragment中都会实现lifecycleOwner接口,返回一个lifecycleRegistry实例,并且各自在实例化lifecycleRegistry时,都会传入this即当前的activity。
ComponentActivity
//分发生命周期事件
ReportFragment.injectIfNeededIn(this);
在每个生命周期中,通过LifecycleRegistry的handleLifecycleEvent方法来处理,移动到下一个生命周期,比如 onPause,此方法就传入Lifecycle.Event.ON_PAUSE,再调用moveToState,转向对应的状态,主要通过sync方法。
private void sync() {
LifecycleOwner lifecycleOwner = mLifecycleOwner.get();
if (lifecycleOwner == null) {
throw new IllegalStateException("LifecycleOwner of this LifecycleRegistry is already"
+ "garbage collected. It is too late to change lifecycle state.");
}
while (!isSynced()) {
mNewEventOccurred = false;
// no need to check eldest for nullability, because isSynced does it for us.
if (mState.compareTo(mObserverMap.eldest().getValue().mState) < 0) {
backwardPass(lifecycleOwner);
}
Map.Entry<LifecycleObserver, ObserverWithState> newest = mObserverMap.newest();
if (!mNewEventOccurred && newest != null
&& mState.compareTo(newest.getValue().mState) > 0) {
forwardPass(lifecycleOwner);
}
}
mNewEventOccurred = false;
}
isSynced()主要判断mObservermap(用于存储LifecycleObserver对象和其关联的EventObserver对象。)中新旧的state是否相等,不相等的话,就进行转移,通过判断mState和mObservermap新旧状态,决定执行forward还是backwardpass。
二、LiveDta
观察者注册
通过observe方法添加。
@MainThread
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);
}
通过addObserver(wrapper)注册观察者,传入LifecycleBoundObserver类型的wrapper。
class LifecycleBoundObserver extends ObserverWrapper implements LifecycleEventObserver
观察者解注册
主要通过 removeObservers 方法,会遍历观察者列表,从中删除对应的观察者。
数据更新
setValue
在主线程中进行调用的,它会直接更新LiveData中的数据并通知所有的观察者进行UI更新;
protected void setValue(T value) {
...
dispatchingValue(null);
}
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;
}
private void considerNotify(ObserverWrapper observer) {
...
observer.mObserver.onChanged((T) mData);
}
最终回调到OnChanged,更新数据。
postValue
在异步线程中进行调用的,它会将要更新的数据封装成PendingPost对象,并提交给主线程的Handler进行处理,最终还是会调用到setValue.
private final Runnable mPostValueRunnable = new Runnable() {
@SuppressWarnings("unchecked")
@Override
public void run() {
Object newValue;
synchronized (mDataLock) {
newValue = mPendingData;
mPendingData = NOT_SET;
}
setValue((T) newValue);
}
};
三、ViewModel
是一个以生命周期感知的方式来保存和管理UI相关的数据的类。可以在activity或fragment重新创建时保存数据的完整性,避免因为生命周期的问题导致数据丢失。
优势:
- 保存数据的完整性。ViewModel 可以在屏幕旋转等配置更改时保存数据并重新创建 Activity 或 Fragment,从而保持数据的完整性,避免因为生命周期变化而导致的数据丢失
- 简化代码:使用 ViewModel 可以将 UI 相关的数据与 UI 控件分离,避免了在 Activity 或 Fragment 中处理数据逻辑的繁琐代码,使代码更加清晰、简洁。
- 支持数据共享:ViewModel不会随着Activity的屏幕旋转而销毁,减少了维护状态的代码成本(数据的存储和读取、序列化和反序列化)。
- 支持响应式编程:ViewModel 可以与 LiveData 或 RxJava 等响应式编程库一起使用,实现数据的实时更新和响应。
劣势:
- 不适合处理长时间运行的任务。viewmodel主要用于管理UI相关的数据
- 数据持久化需要额外处理。保存的数据只是暂时性的
ViewModel简单原理
获取方式,以以下两种方式为例
viewModel = ViewModelProvider.NewInstanceFactory().create(MyViewModel::class.java)
viewModel = ViewModelProvider(this).get(MyViewModel::class.java)
ViewModelProvider
主要定义了如何获取ViewModel,通过两种工厂或者get方法
1.工厂
public interface Factory {
@NonNull
<T extends ViewModel> T create(@NonNull Class<T> modelClass);
}
NewInstanceFactory实现了Factory接口,AndroidViewModelFactory(构造函数需要传入Applciation,可以创建AndroidViewModel,应用上下文感知ViewModel )又继承NewInstanceFactory。它们实现了create方法,传入一个Class,并返回它的实例
public <T extends ViewModel> T create(@NonNull Class<T> modelClass) {
//noinspection TryWithIdenticalCatches
try {
return modelClass.newInstance();
} catch (InstantiationException e) {
throw new RuntimeException("Cannot create an instance of " + modelClass, e);
} catch (IllegalAccessException e) {
throw new RuntimeException("Cannot create an instance of " + modelClass, e);
}
}
2.get方法
ViewModelProvider构造函数中,需要一个ViewModelStoreOwner参数,同lifecycle,一般是activity和fragment。
public interface ViewModelStoreOwner {
@NonNull
ViewModelStore getViewModelStore();
}
最终都会调用这个构造函数来初始化。
public ViewModelProvider(@NonNull ViewModelStore store, @NonNull Factory factory) {
mFactory = factory;
mViewModelStore = store;
}
public <T extends ViewModel> T get(@NonNull String key, @NonNull Class<T> modelClass) {
//mViewModelStore通过key获取对应的viewmodel
ViewModel viewModel = mViewModelStore.get(key);
//如果传入的modelClass和获取到的viewModel相同,或者为它的子类等
if (modelClass.isInstance(viewModel)) {
if (mFactory instanceof OnRequeryFactory) {
((OnRequeryFactory) mFactory).onRequery(viewModel);
}
return (T) viewModel;
} else {
//noinspection StatementWithEmptyBody
if (viewModel != null) {
// TODO: log a warning.
}
}
//根据不同的参数创建viewModel,
if (mFactory instanceof KeyedFactory) {
viewModel = ((KeyedFactory) mFactory).create(key, modelClass);
} else {
viewModel = mFactory.create(modelClass);
}
//每次创建完成,都添加进去
mViewModelStore.put(key, viewModel);
return (T) viewModel;
}
ViewModelStore
存储ViewModel类,通过Map存储
public class ViewModelStore {
//key-value来保存ViewModel
private final HashMap<String, ViewModel> mMap = new HashMap<>();
final void put(String key, ViewModel viewModel) {
ViewModel oldViewModel = mMap.put(key, viewModel);
if (oldViewModel != null) {
oldViewModel.onCleared();
}
}
final ViewModel get(String key) {
return mMap.get(key);
}
Set<String> keys() {
return new HashSet<>(mMap.keySet());
}
/**
* 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();
}
}
ViweModelProvider获取到ViewModelStore实例,是通过传入的activity或者fragment,在构造函数中调用了owner.getViewModelStore()(或者直接传入ViewModelStore和Factory)。因为activity或者fragment都实现了ViewModelStoreOwner接口,重写了getViewModelStore方法,获取到对应的ViewModelStore实例。
注意:ViewModel 的生命周期不同于 Activity 和 Fragment,它是被系统缓存的,因此可能会出现数据被清除的情况。在使用 ViewModel 时应该注意它的生命周期,及时保存数据并恢复数据。
四、DataBinding
在列表中乱用,因为DataBinding数据绑定是延迟一帧的,如果列表中的ItemView的宽高需要计算后才能正确展示,不建议使用DataBinding操作。否则会看到列表ItemView明显的撑开动画,体验不好。
此处可以使用dataBinding.executePendingBindings()快速渲染布局解决