Jetpack是众多优秀组件的集合。是谷歌推出的一套引领Android开发者逐渐统一开发规范的架构。
Jetpack的优势
基于生命周期感知的能力,可以减少崩溃,,内存泄露,模板代码。为我们开发出健壮且高质量的程序提供保障。
组件可以单独使用,也可以搭配使用,搭配Kotlin语言特性可进一步加速开发。
添加依赖
api "android.arch.navigation:navigation-fragment:2.0.0"
api "android.arch.navigation:navigation-ui:2.0.0"
路由跳转,可携带参数,指定转场动画
NavController navController;
navControll.navigate(int resId,Bundle args,NavOptions navOptions)
deepLink实现页面直达能力
navController.handleDeepLink("/detail/main")
管理Fragment回退栈
navController.popBackStack(int destinationId,boolean inclusive)
2,Lifecycle:具备宿主声明后期感知能力的组件
特性:它持有组件(如Activity或Fragment)生命周期状态的信息,并且允许其他对象观察此状态。
添加依赖
api "androidx.appcompat:appcompat:1.3.0"
api "androidx.lifecycle:lifecycle-common:2.3.1"
Fragment源码,经典用法
public class Fragment implements xxx,LifecycleOwner{
LifecycleRegistry mLifecycleRegistry=new LifecycleRegistry(this);
@Override
public Lifecycle getLifecycle(){
return mLifecycleRegistry;
}
class MyPresenter extends LifecycleObserver{
@OnLifecycleEvent(Lifecycle.Event.ON_CREATE)
ovid onCreate(@NotNull LifecycleOwner owner){}
@OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
ovid onCreate(@NotNull LifecycleOwner owner){}
}
}
getLifecycle().addObserver(mPresenter);//注册观察者,观察者宿主声明周期状态变化
3,ViewModel:具备生命周期感知能力的数据存储组件
特性:页面配置更改数据不丢失,生命周期感应,数据共享
api "androidx.appcompat:appcompat:1.3.0"
api "androidx.lifecycle:lifecycle-viewmodel:2.3.1"
api "androidx.lifecycle:lifecycle-livedata:2.3.1"
ViewModel的使用
class MyViewModel extends ViewModel {
@Override
protected void onCleared() {
super.onCleared();
//宿主销毁时执行,可自我清理释放资源
}
MutableLiveData<ItemData> liveData = new MutableLiveData<>();
public void getItemData(LifecycleOwner owner, Observer<ItemData> observer) {
liveData.observe(owner, observer);
liveData.setValue(itemData);
}
}
ViewModel数据共享
//构建ViewModel实力,需要使用ViewModelProvider来获取ViewModeld对象。
//不同Fragment中获取同一个ViewModel实力,实现数据共享。
class FragmentA extends Fragment {
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
MyViewModel myViewModel = new ViewModelProvider(getActivity().getViewModelStore(),
new ViewModelProvider.NewInstanceFactory())
.get(MyViewModel.class);
}
}
4,LiveData:具备生命周期感知能力的数据订阅,分发组件
MutableLiveData<T> liveData=new MutableLiveData<T>()
//注册一个跟宿主生命周期绑定的观察者,宿主销毁,会自动接触注册
observe(LifecycleOwner owner, Observer<? super T> observer)
//观察不到宿主生命周期,不会自动解除
observeForever(Observer<? super observer>)
//分发数据 只能用在主线程
setValue(T value);
//分发数据 子线程 主线程都可以使用
postValue(T value)
5,Room:轻量级orm数据库,本质上是一个SQLite抽象层
特性:使用更加简单,通过注解的方式实现相关功能。编译时自动生成实现类impl
api "android.arch.persistence.room:runtime:1.1.1"
kapt "android.arch.persistence.room:compiler:1.1.1"
Room使用
//创建操作数据库的实体层
@Dao
public interface UserDao{
@Query("SELECT * FROM user")
List<User> getAll();
@update("update table user set desc=:desc and where user_id = :userId")
User updateUser(String desc,String userId);
@Insert
void insertAll(User...users);
@Delete
void delete(User user);
}
//创建数据库
@Database(entities={User.class,version=1})
public abstract class MyDatabase extends RoomDatabase{
public static MyDatabase myDatabase;
static{
myDatabase=Room.databaseBuilder(getApplicationContext(),AppDatabase.class,"database-name").build();
}
public abstract UserDao userDao();
}
//通过数据库单例对象,获取userDao数据操作对象
myDatabase.userDao().getAll();
6,DataBinding:dataBinding只是一种工具,它解决的是View和数据之间的双向绑定。MVVM是一种架构模式
特性:数据与视图双向绑定,数据绑定空安全,减少模板代码,释放Activity/Fragment
使用DataBinding
android{
dataBinding{
enabled=true
}
}
布局中绑定数据
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
<data>
<variable name="user" type="com.test.app.model.User"/>
<import type="com.test.app.user.UserManager"></import>
</data>
<androidx.constraintlayout.widget.ConstraintLayout>
<TextView
android:layout_width="200dp"//不能使用dataBinding动态绑定
android:text="@{user.name}"//单向绑定数据变更自动通知UI
android:testSize="@{dimen/16sp}"//资源引用
android:text="@{user.name+@string/suffix}"//字符串的拼接需要引用资源
android:test="@{UserManager.getUserName()}"//调用静态方法,类必须先导入
android:onClick="@{()->UserManager.login()}"
/>
<EditText
//双向绑定数据变更自动更新UI,UI变更了也能自动更新user中的name数据
android:text="@={user.name}"
/>
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
7,WorkManager:新一代后台任务管理组件,功能十分丰富。service能做的事情它也能做。
支持周期性任务调度,链式任务调度,丰富的任务约束条件,即便程序退出,依旧能保证任务的执行
api "android.arch.work:work-runtime:1.0.1"
执行任务
//构建任务
class UploadFileWorker extends Worker{
//执行文件上传
public Result doWork(){
return Result.success()
}
}
//执行任务的request对象
OneTimeWorkRequest request=new OneTimeWorkRequest.Builder(UploadFileWorker.class).build()
//把任务加入调度队列
WorkContinuation workContinuation=WorkManager.getInstance(context).beginWith(request)
workContinuation.then(workB).then(workC).enqueue()
8,Paging:列表分页组件,可以轻松完成分页预加载已达到无限滑动的效果
特性:巧妙融合LiveData,提供多种数据源加载方式
不足:不支持列表数据增删改。列表添加HeaderView,FooterView定位不准确。
api “android.arch.paging:runtime:1.0.1”
//1 使用PagedList.Config对象,用以声明以何种方式分页
PagedList.Config config=new PagedList.Config.Builder()
.setPageSize(10)//指定每次分页加载的条目数量
.setInitialLoadSizeHint(12)//指定初始化数据加载的条目数量
.build();
//2 创建数据源工厂类,用来创建数据提供者
DataSource.Factory factory=new DataSource.Factory(){
public DataSource create(){
return new ItemKeyedDataSource();
}
};
//3 构建一个能够触发加载页面初始化数据的LiveData对象,并且把上面创建的DataSource.Factory和PagedList
LiveData<PagedList<T>> pageData=new LivePagedListBuilder(factory,config).build();
//4 拿到构建出来的LiveData对象注册一个Observer观察者,触发页面数据变化
mViewModel.getPageData().observe(this,pagedList->submitList(pagedList));
class MyItemKeyedDataSource extends ItemKeyedDataSource<GoodsModel>{
public abstract void loadInitial 省略....{
//页面数据加载
callback.onResult(list)
}
public abstract void loadAfter 省略....{
//向后分页数据加载
callback.onResult(list)
}
public abstract void loadBefore 省略....{
//向前页面数据加载
callback.onResult(list)
}
}
1,Lifecycle的使用
使用1
//1.自定义的LifecycleObserver观察者,用注解声明每个方法观察的宿主状态
//用注解的方式给方法添加对应的事件
public class LocationObserver implements LifecycleObserver{
@OnLifecycleEvent(Lifecycle.Event.ON_START)
void onStart(LifecycleOwner owner){
//开启定位
}
@OnLifecycleEvent(Lifecycle.Event.ON_STOP)
void onStop(LifecycleOwner owner){
//停止定位
}
}
//2. 注册观察者 观察宿主生命周期状态变化
public class LocationFragment extends Fragment{
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
LocationObserver observer=new LocationObserver();
getLifecycle().addObserver(observer);
}
}
使用2
public interface FullLifecycleObserver extends LifecycleObserver {
void onCreate(LifecycleOwner owner);
void onStart(LifecycleOwner owner);
void onResume(LifecycleOwner owner);
void onPause(LifecycleOwner owner);
void onStop(LifecycleOwner owner);
void onDestroy(LifecycleOwner owner);
}
class LocationObserver extends FullLifecycleObserver{
void onStart(LifecycleOwner owner){}
void onStop(LifecycleOwner owner){}
}
使用3
public interface LifecycleEventObserver extends LifecycleObserver {
/**
* Called when a state transition event happens.
*
* @param source The source of the event
* @param event The event
*/
void onStateChanged(@NonNull LifecycleOwner source, @NonNull Lifecycle.Event event);
}
public class LocationObserver implements LifecycleEventObserver {
@Override
public void onStateChanged(@NonNull LifecycleOwner source, @NonNull Lifecycle.Event event) {
//监听宿主生命周期状态
}
}
2,Lifecycle在Fragment源码中的实现
//Fragment源码中部分片段
//Fragment实现了LifecycleOwner注册到LifecycleRegistry 在各个生命周期中调用handleLifecycleEvent
public class Fragment implements LifecycleOwner{
LifecycleRegistry mLifecycleRegistry=new LifecycleRegistry(this);
@NonNull
@Override
public Lifecycle getLifecycle() {
return mLifecycleRegistry;
}
void onCreate(){
mLifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_CREATE);
}
void performStart(){
mLifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_START);
}
void performResume(){
mLifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_RESUME);
}
...
}
Fragment源码中涉及到了三个类LifecycleOwner,Lifecycle,LifecycleRegistry,它们三者的关系如下图:
3,Lifecycle在ComponentActivity源码中的实现
//ComponentActivity 源码中部分片段
public class ComponentActivity implements LifecycleOwner{
LifecycleRegistry mLifecycleRegistry=new LifecycleRegistry(this);
@NonNull
@Override
public Lifecycle getLifecycle() {
return mLifecycleRegistry;
}
protected void onCreate(Bundle bundle){
super.onCreate(bundle);
//往Activity上添加一个fragment,用以报告生命周期的变化
//目的是为了兼顾不是继承自AppCompactActivity的场景
ReportFragment.injectIfNeededIn(this);
}
}
//ReportFragment 代码片段
public class ReportFragment extends Fragment {
private static final String REPORT_FRAGMENT_TAG = "androidx.lifecycle"
+ ".LifecycleDispatcher.report_fragment_tag";
public static void injectIfNeededIn(Activity activity) {
// ProcessLifecycleOwner should always correctly work and some activities may not extend
// FragmentActivity from support lib, so we use framework fragments for activities
android.app.FragmentManager manager = activity.getFragmentManager();
if (manager.findFragmentByTag(REPORT_FRAGMENT_TAG) == null) {
manager.beginTransaction().add(new ReportFragment(), REPORT_FRAGMENT_TAG).commit();
// Hopefully, we are the first to make a transaction.
manager.executePendingTransactions();
}
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
dispatchCreate(mProcessListener);
dispatch(Lifecycle.Event.ON_CREATE);
}
@Override
public void onStart() {
super.onStart();
dispatchStart(mProcessListener);
dispatch(Lifecycle.Event.ON_START);
}
private void dispatch(Lifecycle.Event event) {
Activity activity = getActivity();
if (activity instanceof LifecycleRegistryOwner) {
((LifecycleRegistryOwner) activity).getLifecycle().handleLifecycleEvent(event);
return;
}
if (activity instanceof LifecycleOwner) {
Lifecycle lifecycle = ((LifecycleOwner) activity).getLifecycle();
if (lifecycle instanceof LifecycleRegistry) {
((LifecycleRegistry) lifecycle).handleLifecycleEvent(event);
}
}
}
}
从ComponentActivity 源码中可以看出LifecycleRegistry并没有在各个生命周期中去分发事件,而是通过ReportFragment 去实现,目的是为了兼顾不是继承自ComponentActivity 的场景。
如果继承了Activity自己实现了Lifecycle,这时会有个类LifecycleDispatcher,在此类DispatcherActivityCallback中又看到了ReportFragment的身影。
这就说明,如果没有继承ComponentActivity ,只要实现了LifecycleOwner接口,也能感知生命周期变化。
class LifecycleDispatcher {
private static AtomicBoolean sInitialized = new AtomicBoolean(false);
static void init(Context context) {
if (sInitialized.getAndSet(true)) {
return;
}
((Application) context.getApplicationContext())
.registerActivityLifecycleCallbacks(new DispatcherActivityCallback());
}
@SuppressWarnings("WeakerAccess")
@VisibleForTesting
static class DispatcherActivityCallback extends EmptyActivityLifecycleCallbacks {
@Override
public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
ReportFragment.injectIfNeededIn(activity);
}
}
}
4,LifecycleRegistry 源码分析
addObserver方法分析
@Override
public void addObserver(@NonNull LifecycleObserver observer) {
//注释1 State
State initialState = mState == DESTROYED ? DESTROYED : INITIALIZED;
ObserverWithState statefulObserver = new ObserverWithState(observer, initialState);
ObserverWithState previous = mObserverMap.putIfAbsent(observer, statefulObserver);
if (previous != null) {
return;
}
LifecycleOwner lifecycleOwner = mLifecycleOwner.get();
if (lifecycleOwner == null) {
// it is null we should be destroyed. Fallback quickly
return;
}
boolean isReentrance = mAddingObserverCounter != 0 || mHandlingEvent;
State targetState = calculateTargetState(observer);
mAddingObserverCounter++;
//注释2 while 循环
while ((statefulObserver.mState.compareTo(targetState) < 0
&& mObserverMap.contains(observer))) {
pushParentState(statefulObserver.mState);
statefulObserver.dispatchEvent(lifecycleOwner, upEvent(statefulObserver.mState));
popParentState();
// mState / subling may have been changed recalculate
targetState = calculateTargetState(observer);
}
if (!isReentrance) {
// we do sync only on the top level.
sync();
}
mAddingObserverCounter--;
}
注释1 State : 当前宿主的状态,并不是宿主的生命周期状态。两者的关系如下图:
对于两者的状态又是怎么通过代码实现的呢,我们主要来分析一下while中的代码。
注释2 while 循环:
while用到的几个关键方法:
while循环代码中的逻辑处理,是让观察者收到宿主完整的生命周期状态。例如:宿主在onResume生命周期注册一个observer,需要把宿主的onCreate,onStart,onResume都分发给observer。
再来看LifecycleRegistry 中的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);
}
Entry<LifecycleObserver, ObserverWithState> newest = mObserverMap.newest();
if (!mNewEventOccurred && newest != null
&& mState.compareTo(newest.getValue().mState) > 0) {
forwardPass(lifecycleOwner);
}
}
mNewEventOccurred = false;
}
状态分发如何区分观察者类型,也就是如何区分LifecycleObserver ,FullLifecycleObserver ,LifecycleEventObserver 。
static class ObserverWithState {
State mState;
LifecycleEventObserver mLifecycleObserver;
ObserverWithState(LifecycleObserver observer, State initialState) {
mLifecycleObserver = Lifecycling.lifecycleEventObserver(observer);
mState = initialState;
}
void dispatchEvent(LifecycleOwner owner, Event event) {
State newState = getStateAfter(event);
mState = min(mState, newState);
mLifecycleObserver.onStateChanged(owner, event);
mState = newState;
}
}
在Lifecycling类中的方法,在这里进行了类型的区分。
@NonNull
static LifecycleEventObserver lifecycleEventObserver(Object object) {
boolean isLifecycleEventObserver = object instanceof LifecycleEventObserver;
boolean isFullLifecycleObserver = object instanceof FullLifecycleObserver;
if (isLifecycleEventObserver && isFullLifecycleObserver) {
return new FullLifecycleObserverAdapter((FullLifecycleObserver) object,
(LifecycleEventObserver) object);
}
if (isFullLifecycleObserver) {
return new FullLifecycleObserverAdapter((FullLifecycleObserver) object, null);
}
if (isLifecycleEventObserver) {
return (LifecycleEventObserver) object;
}
final Class<?> klass = object.getClass();
int type = getObserverConstructorType(klass);
概念:LiveData组件是JetPack推出的基于观察者的消息订阅/分发组件,具有宿主(Activity,Fragment)生命周期感知能力,可以确保LiveData仅分发消息给处于活跃状态的观察者,即只有处于活跃状态的观察者才能收到消息。
1,基础介绍
LiveData简单使用
//1.注册观察者
liveData.observer(this,new Observer<User>{
void onChanged(User user){
}
})
//2.发送消息
liveData.postValue(data);
MutableLiveData: 在使用LiveData做消息分发的时候,需要使用此类。只有拿到MutableLiveData对象才可以发送消息,LiveData对象只能接收消息,避免拿到LiveData对象既能发消息也能收消息。
public class MutableLiveData<T> extends LiveData<T> {
public MutableLiveData(T value) {
super(value);
}
public MutableLiveData() {
super();
}
@Override
public void postValue(T value) {
super.postValue(value);
}
@Override
public void setValue(T value) {
super.setValue(value);
}
}
MediatorLiveData: 可以统一观察多个LiveData发射的数据进行统一处理,同时也可以做为一个liveData,被其他observer观察。
//创建两个LiveData对象
LiveData<String> liveData1=new MutableLiveData();
LiveData<String> liveData2=new MutableLiveData();
//创建一个聚合类MediatorLiveData
MediatorLiveData<String> liveDataMerger=new MediatorLiveData<>();
liveDataMerger.addSource(liveData1,observer);
liveDataMerger.addSource(liveData2,observer);
Observer observer=new Observer<String>(){
@Override
public void onChanged(String string){
}
}
Transformations.map操作符: 可以对liveData进行变化,返回一个新的liveData对象。
MutableLiveData<Integer> liveData=new MutableLiveData();
//数据转换
LiveData<Integer> transformData=Transformations.map(data,input -> String.valueOf(input))
//使用转换后的transformData去观察数据
transformData.observe(this,output ->{
});
//发送数据
liveData.setValue(10);
LiveData核心方法
方法名 | 作用 |
---|---|
observe(LifecycleOwner owner,Observer observer) | 注册和宿主生命周期关联的观察者 |
observeForever(Observer observer) | 注册观察者,不会反注册 |
setValue(T data) | 发送数据,没有活跃观察者时不分发。只能在主线程 |
postValue(T data) | 和setValue一样。但不受线程环境限制 |
onActive | 当且仅当有一个活跃的观察者时会触发 |
inActive | 不存在活跃的观察者时触发 |
2,LiveData消息分发原理
黏性消息分发流程
普通消息分发流程
LiveData源码中的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);
}
LifecycleBoundObserver源码,LifecycleBoundObserver实现了LifecycleEventObserver接口。在onStateChanged方法中,首先会判断当前宿主生命周期状态,如果是DESTROYED会移除当前消息。
class LifecycleBoundObserver extends ObserverWrapper implements LifecycleEventObserver {
@NonNull
final LifecycleOwner mOwner;
LifecycleBoundObserver(@NonNull LifecycleOwner owner, Observer<? super T> observer) {
super(observer);
mOwner = owner;
}
@Override
boolean shouldBeActive() {
return mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED);
}
@Override
public void onStateChanged(@NonNull LifecycleOwner source,
@NonNull Lifecycle.Event event) {
Lifecycle.State currentState = mOwner.getLifecycle().getCurrentState();
if (currentState == DESTROYED) {
removeObserver(mObserver);
return;
}
Lifecycle.State prevState = null;
while (prevState != currentState) {
prevState = currentState;
activeStateChanged(shouldBeActive());
currentState = mOwner.getLifecycle().getCurrentState();
}
}
}
再看considerNotify方法中的mLastVersion 和mVersion。mLastVersion 和mVersion默认值都是-1。当调用setValue方法时mVersion会加1,这时mVersion就大于mLastVersion ,从而执行onChanged方法。
private void considerNotify(ObserverWrapper observer) {
if (!observer.mActive) {
return;
}
if (!observer.shouldBeActive()) {
observer.activeStateChanged(false);
return;
}
if (observer.mLastVersion >= mVersion) {
return;
}
observer.mLastVersion = mVersion;
observer.mObserver.onChanged((T) mData);
}
基于LiveData的改造
在源码中,我们知道在LiveData和Observer中有个version字段,当发送一条消息,和接收一条消息,通过version判断,以免消息重复发送。但是如果是黏性事件,先发送消息,后注册事件,那么就会有问题。
那么我们基于LiveData来实现一个不用反注册,且支持黏性事件的消息总线。
object HiDataBus {
private val eventMap = ConcurrentHashMap<String, StickyLiveData<*>>()
fun <T> with(eventName: String): StickyLiveData<T> {
var liveData = eventMap[eventName]
if (liveData == null) {
liveData = StickyLiveData<T>(eventName)
eventMap[eventName] = liveData
}
return liveData as StickyLiveData<T>
}
class StickyLiveData<T>(private val eventName: String) : LiveData<T>() {
var mStickyData: T? = null
var mVersion = 0
fun setStickyData(stickyData: T) {
mStickyData = stickyData
setValue(stickyData)
}
fun postStickyData(stickyData: T) {
mStickyData = stickyData
postValue(stickyData)
}
override fun setValue(value: T) {
mVersion++
super.setValue(value)
}
override fun postValue(value: T) {
mVersion++
super.postValue(value)
}
override fun observe(owner: LifecycleOwner, observer: Observer<in T>) {
observerSticky(owner, false, observer)
}
private fun observerSticky(
owner: LifecycleOwner,
sticky: Boolean,
observer: Observer<in T>
) {
owner.lifecycle.addObserver(LifecycleEventObserver { source, event ->
if (event == Lifecycle.Event.ON_DESTROY) {
eventMap.remove(eventName)
}
})
super.observe(owner, StickyObserver(this, sticky, observer))
}
}
class StickyObserver<T>(
private val stickyLiveData: StickyLiveData<T>,
private val sticky: Boolean,
private val observer: Observer<in T>
) : Observer<T> {
private var lastVersion = stickyLiveData.mVersion
override fun onChanged(t: T) {
if (lastVersion >= stickyLiveData.mVersion) {
if (sticky && stickyLiveData.mStickyData != null) {
observer.onChanged(stickyLiveData.mStickyData)
}
return
}
lastVersion = stickyLiveData.mVersion
observer.onChanged(t)
}
}
}
使用方法
//发送消息
HiDataBus.with<String>("sticky").setStickyData("hello word")
//接受消息 sticky=true 可以接收黏性消息
HiDataBus.with<String>("sticky").observerSticky(this,true, Observer {
Toast.makeText(this,it,Toast.LENGTH_LONG).show()
})
概念:ViewModel具备宿主生命周期感知能力,保存数据在页面因配置变更导致页面销毁重建之后依然存在。
1,ViewModel的用法
**常规用法:**存储数据,仅仅只能当页面因为配置变更导致的销毁再重建时可复用。复用的是ViewModel的实例对象整体。
class TestViewModel():ViewModel(){
val liveData=MutableLiveData<List<GoodsModel>>()
fun loadInitData():LiveData<List<GoodsModel>>{
if(liveData.value=null){
val remoteData=fetchDataFromRemote()
liveData.postValue(remoteData)
}
return liveData
}
}
//通过ViewModelProvider来获取ViewModel对象
val viewModel=ViewModelProvider(this).get(TestViewModel::class.java)
viewModel.loadPageData().observer(this,Observer{
})
**进阶用法:**存储的数据,无论是配置变更,还是内存不足,电量不足等系统原因导致页面被回收再重建,都可以复用。即便ViewModel不是同一个实例,它存储的数据也能做到复用。需要引入savedstate组件
api 'androidx.lifecycle:lifecycle-viewmodel-savedstate:2.2.0'
class TestViewModel(val savedState:SavedStateHandle):ViewModel(){
private val KEY_HOME_PAGE_DATA="key_home_page_data"
private val liveData=MutableLiveData<List<GoodsModel>>()
fun loadInitData():LiveData<List<GoodsModel>>{
if(liveData.value=null){
val memoryData=savedState.get<List<GoodsModel>>(KEY_HOME_PAGE_DATA)
liveData.postValue(memoryData)
return liveData
}
val remoteData=fetchDataFromRemote()
savedState.set(KEY_HOME_PAGE_DATA,remoteData)
liveData.postValue(remoteData)
}
return liveData
}
跨页面数据共享
class MyApp:Application(),ViewModelStoreOwner{
private val appViewModelStore:ViewModelStore by lazy{
ViewModelStore()
}
override fun getViewModelStore():ViewModelStore{
return appViewModelStore
}
}
val viewmodel=ViewProvider(application).get(TestViewModel::class.java)
2,配置变更ViewModel复用原理
获取ViewModel实例
al viewModel=ViewModelProvider(this).get(TestViewModel::class.java)
在ViewModelProvider存在一个ViewModelStore 类用于存储ViewModel对象。
public ViewModelProvider(@NonNull ViewModelStore store, @NonNull Factory factory) {
mFactory = factory;
mViewModelStore = store;
}
get方法获取当前实例,如果实例不存在ViewModelStore, 那么会通过Factory去创建实例。
public <T extends ViewModel> T get(@NonNull String key, @NonNull Class<T> modelClass) {
ViewModel viewModel = mViewModelStore.get(key);
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.
}
}
if (mFactory instanceof KeyedFactory) {
viewModel = ((KeyedFactory) mFactory).create(key, modelClass);
} else {
viewModel = mFactory.create(modelClass);
}
mViewModelStore.put(key, viewModel);
return (T) viewModel;
}
在ComponentActivity中获取ViewModelStore 对象
public ViewModelStore getViewModelStore() {
if (getApplication() == null) {
throw new IllegalStateException("Your activity is not yet attached to the "
+ "Application instance. You can't request ViewModel before onCreate call.");
}
if (mViewModelStore == null) {
NonConfigurationInstances nc =
(NonConfigurationInstances) getLastNonConfigurationInstance();
if (nc != null) {
// Restore the ViewModelStore from NonConfigurationInstances
mViewModelStore = nc.viewModelStore;
}
if (mViewModelStore == null) {
mViewModelStore = new ViewModelStore();
}
}
return mViewModelStore;
}
在ComponentActivity中存储ViewModelStore对象,这里就是关键,通过onRetainNonConfigurationInstance这个方法存储ViewModel对象,从而实现Activity配置变化后对ViewModel的复用。
public final Object onRetainNonConfigurationInstance() {
Object custom = onRetainCustomNonConfigurationInstance();
ViewModelStore viewModelStore = mViewModelStore;
if (viewModelStore == null) {
// No one called getViewModelStore(), so see if there was an existing
// ViewModelStore from our last NonConfigurationInstance
NonConfigurationInstances nc =
(NonConfigurationInstances) getLastNonConfigurationInstance();
if (nc != null) {
viewModelStore = nc.viewModelStore;
}
}
if (viewModelStore == null && custom == null) {
return null;
}
NonConfigurationInstances nci = new NonConfigurationInstances();
nci.custom = custom;
nci.viewModelStore = viewModelStore;
return nci;
}
ViewModel数据复用savedState组件
**SavedStateRegistry模型:**一个总Bundle,key-value存储着每个ViewModel对应字bundle
SavedState数据存储流程: 逐一调用每个SavedStateHandle保存自己的数据。汇总成一个总的Bundle,再存储到Activity的SavedState对象中。
SavedState数据复用流程(1): 从Activity的saveState恢复所有ViewModel数据到SavedStateRegistry
SavedState数据复用流程(2): 创建ViewModel并传递恢复的SavedStateHandle
Room搭配LiveData监听数据变更自动刷新页面实现原理
第一次向LiveData注册Observer时触发onActive,从而触发首次数据的懒加载。数据的加载在RefreshRunnable中完成,首次加载数据时会向InvalidationTracker注册监听表数据变更的observer,一旦表数据变更了,则会再次触发RefreshRunnable加载最新数据。
增删改三种操作开始之前会向一张表中写入本次操作的表的成名,并将状态置为1,操作完成后会触发InvalidationTracker.endTranstions。进而查询出所有数据变更了的表。然后回调给每一个RoomTracklingLiveData再次执行refreshRunnable重新加载数据,并发送到UI层的observer刷新页面。