Jetpack架构组件库

前言

三种架构模式区别

MVC(Model-View-Controller)

MVC将应用抽象为数据层(Model)、视图(View)、逻辑(Controller) ,这样数据、视图、逻辑的代码各自汇聚。

MVC的目的就是将M和V的代码分离,且MVC是单向通信,必须通过Controller来承上启下。

问题:但是在MVC模式中,Model和View可能有耦合

nimg.cn/ce50e5d935ae4dfe9aafa8cf30d1da7e.png)

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

Jetpack是众多优秀组件的集合。是谷歌推出的一套引领Android开发者逐渐统一开发规范的架构。

Jetpack的优势

基于生命周期感知的能力,可以减少崩溃,,内存泄露,模板代码。为我们开发出健壮且高质量的程序提供保障。
组件可以单独使用,也可以搭配使用,搭配Kotlin语言特性可进一步加速开发。

二,Jetpack组件库介绍

在这里插入图片描述1,Navigation

  • 特性:Activity,Fragment,Dialog提供路由能力的组件,导航时可携带参数,指定转场动画,支持deepline页面直达,fragment回退栈管理能力。
  • 不足:十分依赖xml文件,不利于模块化,组件化开发。

添加依赖

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)
    }
}

三,使用Jetpack架构开发模式

在这里插入图片描述

四,Lifecycle源码分析

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用到的几个关键方法:

  • calculateTargetState():计算observer应该到达的状态,也就是当前宿主的状态。
  • upEvent():根据当前观察者的状态,判断应该接受哪个事件。
  • getStateAfter():根据分发的事件,判断当前观察者的状态。

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源码分析

概念: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源码分析

概念: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组件

  • SavedStateHandle的数据存储与恢复。即便ViewModel不是同一个实例,它存储的数据也能做到复用。
  • SavedStateRegistryController:用于创建SavedStateRegistry。
  • SavedStateRegistry:数据存储和恢复。
  • SavedStateHandle:单个ViewModel数据存储和恢复。

在这里插入图片描述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刷新页面。
在这里插入图片描述

七,面试思维导图

由于面试过程中往往不知道从何数起,这就需要把琐碎的知识点,汇总一下,理解着分步骤去记忆,这样更有条理,也方便复习。
在这里插入图片描述

  • 0
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: Jetpack是一套基于Android开发语言Kotlin的组件,目的是帮助Android开发者快速构建健壮的、高效的应用程序。Jetpack架构组件从入门到精通是一本介绍Jetpack组件的电子书,其内容向读者提供了Jetpack组件的最基础的知识体系,以及对组件的更高阶的实践知识和技能分享。 在读者学习这本电子书时,首先会学习到基本的Jetpack概念,并了解到如何使用各种工具来实现底层代码、布局和资源文件的编写。同时,电子书重点讲解了Jetpack组件中最常用的组件,比如ViewModel、LiveData、Room、WorkManager等,它们各自的功能和用法,让读者熟知Jetpack组件的基本运作原理。读者还会学习如何将这些组件综合使用,以构造真正的应用程序。在内容的后半部分,电子书重点讲解了Jetpack架构层面的设计,以及如何更有效的使用和管理组件。 总之,Jetpack架构组件从入门到精通这本电子书非常适合想要学习Jetpack组件的Android初学者和有一定开发经验的开发者,能够帮助他们快速掌握Jetpack组件,以及提高软件的可扩展性和有效性。 ### 回答2: Jetpack架构组件是一组Android软件组件,通过这些组件,开发者可以更加轻松地开发应用程序,并提供高质量的用户体验。Jetpack架构组件包括众多不同的组件,这些组件都具有不同的用途和功能。对于开发者来说,学习Jetpack架构组件是非常重要的。 《jetpack架构组件从入门到精通 pdf》是一份针对Jetpack架构组件的学习资料。它是可以帮助开发者更好地理解和掌握Jetpack架构组件的重要手册。通过这份PDF文档,开发者可以学习到Jetpack架构组件的基本概念、用途和功能,并了解如何将这些组件应用到他们的应用程序开发中。 这份PDF文档涵盖了Jetpack架构组件的多个方面,包括ViewModel、LiveData、Data Binding、Room、Navigation、WorkManager等等。每个章节都包含了详细的介绍和具体的用例,从而帮助开发者更好地理解每个组件的用途和功能。 无论是初学者还是经验丰富的开发者,都可以从这份PDF文档中获益。它可以帮助初学者更轻松地入门Jetpack架构组件,并提供了有用的工具和技巧。对于经验丰富的开发者来说,这份PDF文档可以帮助他们更深入地了解Jetpack架构组件,并提供了一些高级技术和策略,以优化应用程序性能和用户体验。 总之,Jetpack架构组件从入门到精通的PDF文档是一份非常有价值的资源,它可以帮助开发者更好地理解和掌握Jetpack架构组件,从而更加轻松地开发高质量的Android应用程序。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值