一、什么是Jetpack?
Jetpack并不是一个框架或者组件,它是一套库、工具和指南的集合,可帮助开发者更轻松地编写优质应用。这些组件可帮助开发者遵循最佳做法、摆脱编写样板代码的工作并简化复杂任务,以便将精力集中放在所需的代码上。
Android Jetpack中的很多组件并不都是新开发的,而是很早就有了,比如在Goole I/O 2017大会时推出了 Android Architecture Component(AAC),它包括了LifeCycle、LiveData、ViewModel、Room。在Goole I/O 2018大会上,
用AndroidX替代了Android Support Library,并在Android Architecture Component的基础上发布了Android Jetpack,AndroidX也是属于Android Jetpack。
Jetpack主要特性有以下三点:
1.加速开发
组件可单独使用,也可以协同工作,当使用kotlin语言特性时,可以提高效率。
2.消除样板代码
Android Jetpack可管理繁琐的Activity(如后台任务、导航和生命周期管理)。
3.构建高质量的强大应用
Android Jetpack组件围绕现代化设计实践构建而成,具有向后兼容性,可以减少崩溃和内存泄漏。
二、Android Jetpack架构组件 Lifecycle
2.1 什么是Lifecycle
Lifecycle用于帮助开发者管理Activity和Fragment 的生命周期
2.2 Lifecycle基本用法
先不谈Activity和Fragment中如何使用,先举一个Lifecycle的简单例子。
public class MyObserver implements LifecycleObserver {
@OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
public void connectListener() {
...
}
@OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)
public void disconnectListener() {
...
}
}
myLifecycleOwner.getLifecycle().addObserver(new MyObserver());//1
复制代码新建一个MyObserver类,它实现了LifecycleObserver接口,说明MyObserver成为了一个Lifecycle的观察者。
然后在注释1处将MyObserver添加到LifecycleOwner中。LifecycleOwner是一个接口,其内部只有一个方法getLifecycle(),getLifecycle方法用于获取Lifecycle,这样就可以将MyObserver添加到Lifecycle中,当Lifecycle的生命周期发生变化时,MyObserver就会观察到,或者说是感知到。
如果使用是Java8 ,那么可以使用DefaultLifecycleObserver来替代LifecycleObserver:
class MyObserver implements DefaultLifecycleObserver {
@Override
public void onCreate(LifecycleOwner owner) {
...
}
}
复制代码除此之外,不要忘了在build.gradle添加 "androidx.lifecycle:common-java8:<version>"
2.3.Lifecycle应用举例
应用举例准备两个示例,在Activity中使用
package com.example.lifecycledemo1;
import android.arch.lifecycle.Lifecycle;
import android.arch.lifecycle.LifecycleObserver;
import android.arch.lifecycle.OnLifecycleEvent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
public class MainActivity extends AppCompatActivity {
private static final String TAG = "MainActivity";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
getLifecycle().addObserver(new MyObserver());//1
}
public class MyObserver implements LifecycleObserver{
@OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
void onResume(){
Log.d(TAG, "Lifecycle call onResume");
}
@OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)
void onPause(){
Log.d(TAG, "Lifecycle call onPause");
}
}
@Override
protected void onResume() {
super.onResume();
Log.d(TAG, "onResume");
}
@Override
protected void onPause() {
super.onPause();
Log.d(TAG, "onPause");
}
}
复制代码先实现MyObserver,对ON_CREATE和ON_RESUME事件进行监听。因为在Android Support Library 26.1.0 及其之后的版本,Activity和Fragment已经默认实现了LifecycleOwner接口,所以在注释1处可以直接使用getLifecycle方法获取Lifecycle对象,这样MyObserver就可以观察MainActivity的生命周期变化了,LifecycleOwner可以理解为被观察者,MainActivity默认实现了LifecycleOwner接口,也就是说MainActivity是被观察者。
运行程序,打印的log如下所示。
D/MainActivity: onResume
D/MainActivity: Lifecycle call onResume
D/MainActivity: Lifecycle call onPause
D/MainActivity: onPause
只要在MainActivity的onCreate方法中添加MyObserver,那么MyObserver就可以观察到MainActivity的各个生命周期的变化。
三、Android Jetpack架构组件 LiveData
3.1 什么是LiveData
LiveData是一个感知数据变化的持有者,一般是感知Viewmodel的数据!
LiveData如同它的名字一样,是一个可观察的数据持有者,和常规的observable不同,LiveData是具有生命周期感知的,这意味着它能够在Activity、Fragment、Service中正确的处理生命周期。
LiveData的数据源一般是ViewModel,也可以是其它可以更新LiveData的组件。当数据更新后,LiveData 就会通知它的所有观察者,比如Activiy。与RxJava的方法不同的是,LiveData并不是通知所有观察者,它 只会通知处于Active状态的观察者,如果一个观察者处于Paused或Destroyed状态,它将不会收到通知。
这对于Activiy和Service特别有用,因为它们可以安全地观察LiveData对象而不用担心内存泄漏的问题。开发者也不需要在onPause或onDestroy方法中解除对LiveData的订阅。还有一点需要注意的是一旦观察者重新恢复Resumed状态,它将会重新收到LiveData的最新数据。
3.2 LiveData的基本用法
LiveData是一个抽象类,它的最简单的实现类为MutableLiveData,这里举个最简单的例子。
public class MainActivity extends AppCompatActivity {
private static final String TAG="MainActivity";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
MutableLiveData<String> mutableLiveData = new MutableLiveData<>();
//观察者,观察到数据变化显示出来
mutableLiveData.observe(this, new Observer<String>() {//1
@Override
public void onChanged(@Nullable final String s) {
Log.d(TAG, "onChanged:"+s);
}
});
//被观察者数据,异步线程运行
mutableLiveData.postValue("Android进阶三部曲");//2
}
}
注释1处的observe方法有两个参数分别是LifecycleOwner和 Observer<T> ,第一个参数就是MainActivity本身,第二个参数新建了一个Observer<String>,在onChanged方法中得到回调。注释处的postValue方法会在主线程中更新数据,这样就会得到打印的结果。
D/MainActivity: onChanged:Android进阶三部曲
在大多数情况下,LiveData的observe方法会放在onCreate方法中,如果放在onResume方法中,会出现多次调用的问题。除了MutableLiveData的postValue方法,还可以使用setValue方法,它们之前的区别是,setValue方法必须在主线程使用,如果是在工作线程中更新LiveData,则可以使用postValue方法。
3.3 LiveData源码分析
model.getLiveData().observe(this, new Observer<String>() {
@Override
public void onChanged(@Nullable final String newName) {
//响应接受的消息
tvReceiveData.setText(newName);
}
});
1.这个代码必须放到主线程,不然崩溃assertMainThread("observe");
2.Activity生命周期销毁了的话直接退出不执行,所以不会引发内存泄漏
if (owner.getLifecycle().getCurrentState() == DESTROYED) {
return;
}
3.LifecycleBoundObserver装饰器,封装LifecycleOwner,Observer这两个对象
4.owner.getLifecycle().addObserver(wrapper);将观察者与LifecycleOwner进行绑定
5.Activity销毁就取消订阅,因此不会内存泄漏
============================================================================
model.getLiveData().setValue("我是点击按钮发送的消息");
1.for循环遍历所有的观察者
2.调用观察者的observer.mObserver.onChanged((T) mData);因此在每个观察者的onChanged方法可以监听到数据变化。
总结:
1.LiveData 是如何跟 LifecycleOwner 进行绑定,做到感知生命周期的?
答:LifeData 在 observe 方法中用 LifecycleBoundObserver 包装了 observer ,并且通过它绑定了owner。
2.LiveData 会自动在 DESTROY 的状态下取消订阅,是怎么处理的?
答:LifecycleBoundObserver 在 onStateChanged() 方法里处理了生命周期改变的事件,当接收到 DESTROYED 的事件会自动解除跟 owner 的绑定。
生命周期变化后数据处理流程是怎么样的?
LiveData 的实现基于观察者模式;
LiveData 跟 LifecycleOwner 绑定,能感知生命周期变化,并且只会在 LifecycleOwner 处于 Active 状态(STARTED/RESUMED)下通知数据改变;如果数据改变发生在非 active 状态,数据会变化,但是不发送通知,等 owner 回到 active 的状态下,再发送通知;
LiveData 会自动在 DESTROYED 的状态下移除 Observer ,取消订阅,所以不用担心内存泄露;
在 LifecycleOwner 处于 DESTROYED 的状态下,不能订阅;
postValue 方法其实最后调用了 setValue 只不过把操作放到主线程,适合在异步线程里调用,setValue 必须在主线程里调用;
如果同时多次调用 postValue 或 setValue 修改数据,只会修改成最新的那个数据,也即只会收到一次通知(set post混合调用则不一定);
如果 LiveData 有数据,并且 owner 在 active 状态下,那么在订阅的时候,会立马收到一次通知;
一个 Observer 实例,只能绑定一个 LifecycleOwner,而一个 owner 可以绑定多个 Observer 实例;
LiveData 利用版本管理、绑定 Lifecycle 确保了只会发送最新的数据给 active 状态下的 Observer;
LiveData 基于观察者模式,并且可以感知生命周期,这使得我们使用 LiveData 既可以享受观察者模式带来的隔离数据与 UI 等强大的解耦能力,还可以享受感知生命周期带来的巨大便利。并且还无需担心内存泄露这个令人头疼的问题。
四、Android Jetpack架构组件 ViewModel
4.1.什么是ViewModel
ViewModel,感知生命周期的形式来存储和管理视图相关的数据。针对数据。
在说ViewModel前,我们需要解一下MVVM和DataBinding.MVVM最早于2005年被微软的架构师John Gossman提出,在2015年Google I/O大会上发布了MVVM的支持库DataBinding,DataBinding遭到了一些开发者的诟病,主要是绑定数据时如果出现问题会很难排查,这样就没有一个合适的ViewModel规范来帮助开发者来实现MVVM。
在2017年的Google I/O大会上,谷歌推出了ViewModel组件,来规范化ViewModel层。
ViewModel顾名思义,是以感知生命周期的形式来存储和管理视图相关的数据。ViewModel主要有以下的特点:
1.当Activity被销毁时,我们可以使用onSaveInstanceState()方法恢复其数据,这种方法仅适用于恢复少量的支持序列化、反序列化的数据,不适用于大量数据,如用户列表或位图。而ViewModel不仅支持大量数据,还不需要序列化、反序列化操作。
2.Activity/Fragment(视图控制器)主要用于显示视图数据,如果它们也负责数据库或者网络加载数据等操作,那么一旦逻辑过多,会导致视图控制器臃肿,ViewModel可以更容易,更有效的将视图数据相关逻辑和视图控制器分离开来。
3.视图控制器经常需要一些时间才可能返回的异步调用,视图控制器需要管理这些调用,在合适的时候清理它们,以确保它们的生命周期不会大于自身,避免内存泄漏。而ViewModel恰恰可以避免内存泄漏的发生。
4.2.ViewModel基本使用
自定义ViewModel继承ViewMode,实现自定义ViewModel。
import android.arch.lifecycle.LiveData;
import android.arch.lifecycle.MutableLiveData;
import android.arch.lifecycle.ViewModel;
public class MyViewModel extends ViewModel {
private MutableLiveData<String> name;
public LiveData<String> getName() {
if (name == null) {
name = new MutableLiveData<String>();
addName();
}
return name;
}
private void addName() {
name.setValue("Android进阶解密");
}
}
getName方法中创建一个MutableLiveData,并通过MutableLiveData的setValue方法来更新数据。
使用ViewModel然后就可以在Activity中使用MyViewModel了,如下所示。
import android.arch.lifecycle.Observer;
import android.arch.lifecycle.ViewModelProviders;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
public class MainActivity extends AppCompatActivity {
private static final String TAG = "MainActivity";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
MyViewModel model = ViewModelProviders.of(this).get(MyViewModel.class);
model.getName().observe(this, new Observer<String>() {
@Override
public void onChanged(@Nullable String s) {
Log.d(TAG, "畅销书:"+s);
}
});
}
}
通过ViewModelProviders就可以获得MyViewModel的实例,然后配合LiveData就可以观察Name的变化。打印结果为:
D/MainActivity: 书名为Android进阶解密
4.3.ViewModel的生命周期
在旋转设备屏幕时,Activity会被销毁重新创建,而ViewModel却不会这样,它的生命周期如下所示。
可以看到,Activity的生命周期不断变化,经历了被销毁重新创建,而ViewModel的生命周期没有发生变化。
4.4 ViewModel源码解析
MyViewModel model = ViewModelProviders.of(this).get(MyViewModel.class);
1.ViewModel是怎么创建的?
get方法里面反射实例化ViewModel
2.ViewModel是怎么存储的?
ViewModelStore mViewModelStore;
ViewModelStore 结构:HashMap<String, ViewModel>
mViewModelStore.put(key, viewModel);
3.ViewModel为什么可以实现屏幕旋转不丢失数据? 屏幕状态发生改变会拿到上一次屏幕旋转的值
NonConfigurationInstances nc =
(NonConfigurationInstances) getLastNonConfigurationInstance();
ViewModelStore mViewModelStore = nc.viewModelStore;
每次拿到上次屏幕旋转的ViewModelStore ,从而拿到ViewModel
参考资料:
Android Jetpack架构组件(一)带你了解Android Jetpack
https://juejin.cn/post/6844903976815558663
Android Jetpack架构组件(二)一文带你了解Lifecycle(使用篇)
https://juejin.cn/post/6844903977788801032
Android Jetpack架构组件(三)一文带你了解Lifecycle(原理篇)
https://juejin.cn/post/6844903977788817416
Android Jetpack架构组件(四)一文带你了解LiveData(使用篇)
https://juejin.cn/post/6844903982691794957
Android Jetpack架构组件(五)一文带你了解LiveData(原理篇)
https://juejin.cn/post/6844903982691794952
Android Jetpack架构组件(六)一文带你了解ViewModel的使用和原理
https://juejin.cn/post/6844903983471935495