赞
踩
三种架构模式区别
MVC(Model-View-Controller)
MVC将应用抽象为数据层(Model)、视图(View)、逻辑(Controller) ,这样数据、视图、逻辑的代码各自汇聚。
MVC的目的就是将M和V的代码分离,且MVC是单向通信,必须通过Controller来承上启下。
问题:但是在MVC模式中,Model和View可能有耦合
MVP(Model-View-Presenter)
在MVC框架中,View层可以通过访问Model层来更新,但在MVP框架中,View层不能再直接访问Model层,必须通过Presenter层提供的接口,然后Presenter层再去访问Model层。各部分之间的通信是双向。
问题:Presenter的负担很重,Presenter需要知道View和Model的结构,并且在Model变化时候需要手动操作View,增加编码负担,降低代码维护性。
MVVM(Model-View-ViewModel)
MVVM设计了VM层,即ViewModel层,ViewModel自动同步数据到视图,用VM代替P之后,MVVM自动从Model映射到View(实现方式是模板渲染),不需要用户手动操作视图。
Jetpack是众多优秀组件的集合。是谷歌推出的一套引领Android开发者逐渐统一开发规范的架构。
Jetpack的优势
基于生命周期感知的能力,可以减少崩溃,,内存泄露,模板代码。为我们开发出健壮且高质量的程序提供保障。
组件可以单独使用,也可以搭配使用,搭配Kotlin语言特性可进一步加速开发。
1,Navigation
添加依赖
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刷新页面。
由于面试过程中往往不知道从何数起,这就需要把琐碎的知识点,汇总一下,理解着分步骤去记忆,这样更有条理,也方便复习。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。