1. Jetpack是什么?
Jetpack 是一个由多个库组成的套件,可帮助开发者遵循最佳做法、减少样板代码并编写可在各种 Android 版本和设备中一致运行的代码,让开发者可将精力集中于真正重要的编码工作。
Jectpack组件可分为以下四类:
下面主要分享Architecture架构组件:
-
Lifecycle
构建生命周期感知型组件,这些组件可以根据 Activity 或 Fragment 的当前生命周期状态调整行为。
-
LiveData
是一种可观察的数据,构建数据对象,在基础数据改变时通知视图。
-
DataBinding
使用声明性格式,将布局中的界面组件绑定到应用中的数据源,实现数据UI双向绑定。
-
ViewModel
存储界面相关的数据,这些数据不会在应用旋转时销毁,是一种数据容器。
-
Room
创建、存储和管理由 SQLite 数据库支持的持久性数据。
-
Paging
页面中加载数据,在 RecyclerView 中呈现,数据较多时,一种分页组件。
-
Navagation
构建和组织应用内界面,处理深层链接以及在屏幕之间导航,主要用于Activity和Fragment之间导航。
-
Workmanager
管理项目中常见的任务。
谷歌官方推荐的Android应用架构如下图所示:
这些架构组件既可以配合使用,也可以单独使用。
2. Lifecycle
2.1 Lifecyle使用流程
Activity/Fragment作为被观察者,实现LifecycleOwer接口,观察者UserClass实现LifecycleObserver接口,实现与生命周期相关的方法。被观察者中通过调用getLifecycle().addObserver(userCalss);完成订阅关系。当被观察者生命周期发生变化时,会调用观察者中实现的LifecycleObserver的对应方法。
2.2 Lifecyle原理
Lifecycle原理分两步来理解:注册观察者、激活观察者
2.2.1 注册观察者
在LifecycleRegister类的addObserver方法,生成了一个ObserverWithState对象,然后放入FastSafeIterableMap中,其中ObserverWithState包含观察者实现的LifecycleObserver中的方法和对应方法的反射对象。
时序图
以下为比较关键的源码:
LifecycleRegister.java
@Override
public void addObserver(@NonNull LifecycleObserver observer) {
//生命周期的状态
State initialState = mState == DESTROYED ? DESTROYED : INITIALIZED;
ObserverWithState statefulObserver = new ObserverWithState(observer, initialState);
ObserverWithState previous = mObserverMap.putIfAbsent(observer, statefulObserver);
.......
}
ClassesInfoCache.java
private CallbackInfo createInfo(Class klass, @Nullable Method[] declaredMethods) {
.......
//获取LifecycleObserver中所有的方法
Method[] methods = declaredMethods != null ? declaredMethods : getDeclaredMethods(klass);
boolean hasLifecycleMethods = false;
for (Method method : methods) {
OnLifecycleEvent annotation = method.getAnnotation(OnLifecycleEvent.class);
if (annotation == null) {
continue;
}
......
//获取注解的值
Lifecycle.Event event = annotation.value();
......
//调用类型和方法包装成Method引用
MethodReference methodReference = new MethodReference(callType, method);
verifyAndPutHandler(handlerToEvent, methodReference, event, klass);
}
CallbackInfo info = new CallbackInfo(handlerToEvent);
mCallbackMap.put(klass, info);
mHasLifecycleMethods.put(klass, hasLifecycleMethods);
return info;
}
private void verifyAndPutHandler(Map<MethodReference, Lifecycle.Event> handlers,
MethodReference newHandler, Lifecycle.Event newEvent, Class klass) {
Lifecycle.Event event = handlers.get(newHandler);
if (event != null && newEvent != event) {
Method method = newHandler.mMethod;
throw new IllegalArgumentException(
"Method " + method.getName() + " in " + klass.getName()
+ " already declared with different @OnLifecycleEvent value: previous"
+ " value " + event + ", new value " + newEvent);
}
if (event == null) {
//注解方法引用、注解值存到map中
handlers.put(newHandler, newEvent);
}
}
2.2.2 激活观察者
AppCompatActivity 实现了LifecycleOwner接口,同时持有实现了Lifecycle的LifecycleRegistry,这个对象就可以将其理解为观察者模式中的Observable,LifecycleRegistr聚合多个LifecycleObserver,生命周期改变时通知LifecycleObserver进行相应的方法调用。
时序图
以下为关键源码:
ComponentActivity.java
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mSavedStateRegistryController.performRestore(savedInstanceState);
//在当前的Activity里添加一个ReportFragment(无UI的fragment)
ReportFragment.injectIfNeededIn(this);
if (mContentLayoutId != 0) {
setContentView(mContentLayoutId);
}
}
ReportFragment.java ReportFragment的生命周期函数,都调用了dispatch()方法。
dispatch()方法则会判断Activity是否实现了LifecycleOwner接口,如果实现了该接口就调用LifecycleRegister的handleLifecycleEvent() 这样生命周期的状态就会借由LifecycleRegistry通知给各个LifecycleObserver从而调用其中对应Lifecycle.Event的方法。
private void dispatch(Lifecycle.Event event) {
Activity activity = getActivity();
if (activity instanceof LifecycleRegistryOwner) {
((LifecycleRegistryOwner) activity).getLifecycle().handleLifecycleEvent(event);
return;
}
//是否实现了LifecycleOwner接口
if (activity instanceof LifecycleOwner) {
Lifecycle lifecycle = ((LifecycleOwner) activity).getLifecycle();
if (lifecycle instanceof LifecycleRegistry) {
((LifecycleRegistry) lifecycle).handleLifecycleEvent(event);
}
}
}
LifecycleRegistry.java
public void handleLifecycleEvent(@NonNull Lifecycle.Event event) {
//获取当前activity应该出现的下一个状态
State next = getStateAfter(event);
moveToState(next);
}
获取下一个状态的逻辑可根据下图分析:
private void moveToState(State next) {
if (mState == next) {
return;
}
//更新现在的状态
mState = next;
if (mHandlingEvent || mAddingObserverCounter != 0) {
mNewEventOccurred = true;
// we will figure out what to do on upper level.
return;
}
mHandlingEvent = true;
sync();
mHandlingEvent = false;
}
private void forwardPass(LifecycleOwner lifecycleOwner) {
//获取addObserver时存储的类缓存
Iterator<Entry<LifecycleObserver, ObserverWithState>> ascendingIterator =
mObserverMap.iteratorWithAdditions();
while (ascendingIterator.hasNext() && !mNewEventOccurred) {
Entry<LifecycleObserver, ObserverWithState> entry = ascendingIterator.next();
ObserverWithState observer = entry.getValue();
while ((observer.mState.compareTo(mState) < 0 && !mNewEventOccurred
&& mObserverMap.contains(entry.getKey()))) {
pushParentState(observer.mState);
//时事件分发
observer.dispatchEvent(lifecycleOwner, upEvent(observer.mState));
popParentState();
}
}
}
3. LiveData
LiveData是一种可观察的数据存储器类。与常规的可观察类不同,LiveData 具有生命周期感知能力,意指它遵循其他应用组件(如 Activity、Fragment 或 Service)的生命周期。这种感知能力可确保 LiveData 仅更新处于活跃生命周期状态的应用组件观察者。
3.1 基本使用
- 定义观察者用以观察livedata中的数据变化。
- livedata订阅observer。
- livedata发送消息通知observer更新数据,通过回调observer中的onChanged方法实现。
livedata发送消息有两种方式:
- setValue:只能在主线程运行
- postValue:只能在子线程中运行
一般一个项目中会有很多个LiveData,我们可以把多个LiveData注册到一条总线上,形成LivaDataBus。Activity负责注册liveData到总线上,观察者订阅总线上的数据变化。
3.2 LiveDate原理
可从liveData订阅observe做为入口,了解其原理。
3.2.1 绑定
LiveDate.java
@MainThread
public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) {
assertMainThread("observe");
//只订阅状态为可见的owner(Activity/Fragment)
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);
}
3.2.2 通知数据变化
绑定完成后,使用setValue与postValue通知观察者。
4. DataBinding
使用声明性格式,将布局中的界面组件绑定到应用中的数据源,实现数据UI双向绑定。
4.1 基本使用
-
gradle文件中启用dataBinding
dataBinding{ enabled true } -
布局文件:
-
添加layout标签
-
使用data标签定义数据源
<data><!--这里面就用来定义数据源--> <variable name="user" type= "com.example.databindingdemo.User"/> </data> -
通过'@{XXX}',设置界面中的组件对应数据
-
-
Activity:
- 获取binding对象
binding= DataBindingUtil.setContentView(this,R.layout.activity_main); - 设置数据
binding.setUser(user);
- 获取binding对象
4.2 dataBinding原理
从使用角度入手,分析其原理:
- 初始化UI:DatabindingUtil.setContentview
- 设置数据:binding.setData
4.2.1 初始化UI
DatabindingUtil.setContentview做的主要事情是,加载布局文,解析XML文件,把布局文件信息保存到 ViewDataBinding对象中。
加载布局文件时,是不能加载data标签的,所以dataBinding把布局文件分成两个文件:
- layout-xml文件:
- xml文件
- 获取ViewDataBinding时序图:
4.2.2 设置数据
public void setUser(@Nullable com.example.databindingdemo.User User) {
//1.注册监听器更新观查者模式发通知需要相关的信息
updateRegistration(0, User);
this.mUser = User;
synchronized(this) {
mDirtyFlags |= 0x1L;
}
//2.通知数据变化,更新UI
notifyPropertyChanged(BR.user);
super.requestRebind();
}
设置数据的过程分为两步:
-
注册监听器
-
更新UI
5. ViewModel
ViewModel的使用,前面已做简单介绍。
- 管理数据,把VIEW中的数据独出来,单独进行管理
- 数据的保存与恢复,比如屏幕转动,用户点回退按钮,或切换语言等操作
- 主要和LiveData与Room组合使用 注意:ViewModel只是用来管理UI的数据的,不能持有View、Activity或者Fragment的引用(小心内存泄露)。
5.1 获取ViewModel流程:
model = ViewModelProviders.of(this).get(NameViewModel.class)
-
ViewModelProviders.of(this)
创建ViewModelStore,ViewModelStore数据结构:HashMap<String, ViewModel>,和Factory,并返回ViewModelProvider。
-
ViewModelProvider.get(NameViewModel.class)
保存ViewModel对象到ViewModelStore,并返回ViewModel对象。
5.2 ViewModel存取流程
屏幕旋转时,AMS通过Binder机制 Activity旋转时,通过调用onRetainCustomNonConfigurationInstance,保存ViewModel,调用getLastNonConfigurationInstance获取缓存的ViewModel。
6. Room
7. Navagation
8. Workmanager
9. JetPack Demo
JetPack 的 ViewModel 与MVVM 的 VM的区别
Jetpack中的ViewModel是一个框架,它的职责边界是做状态管理,通过配合LiveData或者DataBinding可以解决与View层的双向依赖,根本上避免了内存泄漏,同时在单Activity中可以实现fragment之间通信,总的来说就是功能很强大。而MVVM是一种架构思想,所以关于它里面的ViewModel层也是一种思想。虽然Jetpack ViewModel可以当作MVVM中的ViewModel,但这只是Jetpack ViewModel可以实现的功能之一,所以俩不能划等号。