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 getUser() {
return user;
}
}
上面UserProfileViewModel内部持有 UserRepository 中 MutableLiveData的引用,并且提供了获取 MutableLiveData 的方法 getUser(),UserRepository 负责从网络或数据库中获取数据并封装成 MutableLiveData 然后提供给 ViewModel。
我们在 UserProfileFragment 中为 MutableLiveData 注册观察者,如下:
@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() {
@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()方法都做了什么:
@MainThread
public void observe(@NonNull LifecycleOwner owner, @NonNull Observer 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 源码:
class LifecycleBoundObserver extends ObserverWrapper implements GenericLifecycleObserver {
@NonNull final LifecycleOwner mOwner;
LifecycleBoundObserver(@NonNull LifecycleOwner owner, Observer 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 的状态。
好了,看完了观察者,那么我们的LiveData什么时候会通知观察者呢?不用想,肯定是数据更新的时候,而数据的更新是我们代码自己控制的,如请求网络返回User信息后,我们会主动将User放入MutableLiveData中,这里我在UserRepository中直接模拟网络请求如下:
public class UserRepository {
final MutableLiveData data = new MutableLiveData<>();
public MutableLiveData 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 extends LiveData {
@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, ObserverWrapper>> iterator =
mObservers.iteratorWithAdditions(); iterator.hasNext(); ) {
最后
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长,自己不成体系的自学效果低效漫长且无助。
因此我收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点!不论你是刚入门Android开发的新手,还是希望在技术上不断提升的资深开发者,这些资料都将为你打开新的学习之门
如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
id开发的新手,还是希望在技术上不断提升的资深开发者,这些资料都将为你打开新的学习之门**
如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!