Android Hanlder 消息机制知识点汇总

问题

  • 配置变更时 ViewModel、onSaveIntanceState 对于数据的保存和恢复有什么区别?
  • onSaveInstanceState和ViewModel在数据缓存方面的区别?
  • ViewModel 是如何在配置变化重建恢复数据的?
  • SaveStateHandle 的作用?

ViewModel 创建

获取实例时通过下面这个方法:

ViewModelProvider(this).get(MyViewModel::class.java)

public ViewModelProvider(ViewModelStoreOwner owner, Factory factory) {
    // activity/fragment 是直接创建 ViewModelStore 或者 恢复时系统赋值的
    this(owner.getViewModelStore(), factory);
}

public <T extends ViewModel> T get(String key, Class<T> modelClass) {
    //ViewModelStore 内部维护了一个用于储存VM的HashMap。
    ViewModel viewModel = mViewModelStore.get(key);

    if (modelClass.isInstance(viewModel)) {
        if (mFactory instanceof OnRequeryFactory) {
            ((OnRequeryFactory) mFactory).onRequery(viewModel);
        }
        // 缓存里有直接结束
        return (T) viewModel;
    } else {
    }
    if (mFactory instanceof KeyedFactory) {
        //如果无缓存直接通过 factory 创建
        viewModel = ((KeyedFactory) (mFactory)).create(key, modelClass);
    } else {
        viewModel = (mFactory).create(modelClass);
    }
    //然后放到 缓存里
    mViewModelStore.put(key, viewModel);
    return (T) viewModel;
}

// 默认的 factory 创建实例。
private fun <T : ViewModel> create(modelClass: Class<T>, app: Application): T {
    return if (AndroidViewModel::class.java.isAssignableFrom(modelClass)) {
        try {
            modelClass.getConstructor(Application::class.java).newInstance(app)
        } catch (e: NoSuchMethodException) {
            RuntimeException("Cannot create an instance of $modelClass", e)
        }
    } else super.create(modelClass)
}

  • ViewModelStoreOwner: 接口,AppCompatActivity/Fragment实现了该接口。
  • vm 的实例是 ViewModelStore 中拿的,ViewModelStor 内部维护了一个用于储存VM的HashMap。
  • ViewModelStore 是被 activity/fragment 持有的,每个 Activity(Fragment) 都会拥有一个 ViewModelStore 实例。

所以关键问题是看 ViewModelStore 创建路径。

ViewModel 的恢复

ComponentActivity getViewModelStore:

public ViewModelStore getViewModelStore() {
    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;
}

  • 如果有的话直接从NonConfigurationInstances获取。
  • 否则,创建一个新的ViewModelStore对象。

NonConfigurationInstances是什么东西?NonConfigurationInstances 用来缓存不受配置更改影响的数据,

同时,我们还可以在ComponentActivity里面看到一段代码:

getLifecycle().addObserver(new LifecycleEventObserver() {
    @Override
    public void onStateChanged(@NonNull LifecycleOwner source,
                               @NonNull Lifecycle.Event event) {
        if (event == Lifecycle.Event.ON_DESTROY) {
            if (!isChangingConfigurations()) { // 非配置变化造成的销毁
                getViewModelStore().clear();
            }
        }
    }
});

如果Activity是因为配置更改导致onDestroy方法的回调,并不会清空ViewModelStore里面的内容, 即 ViewModel 的缓存。

NonConfigurationInstances 的赋值是在 Activity 的 attach 方法,系统将上次的 NonConfigurationInstances赋值给了新的Activity对象。

ViewModel 的保存

NonConfigurationInstances为啥能保证Activity重建前后,ViewModeStore是同一个对象呢?

performDestroyActivity方法最后会回调到Activity的onDestroy方法,我们可以通过这个方法可以找到ActivtyThread在Activity onDestroy之前做了保存操作。

 public final Object onRetainNonConfigurationInstance() {
     //配置变化时缓存viewModelStore 到 NonConfigurationInstances
    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;
        }
    }

    NonConfigurationInstances nci = new NonConfigurationInstances();
    nci.custom = custom;
    nci.viewModelStore = viewModelStore;
    return nci;
}

ActivityClientRecord performDestroyActivity(IBinder token, boolean finishing, int configChanges, boolean getNonConfigInstance, String reason) {
    if (getNonConfigInstance) {
        // ······
        // retainNonConfigurationInstances方法的作用就是创建一个对象
        r.lastNonConfigurationInstances= r.activity.retainNonConfigurationInstances();
        // ······
    }
    // Activity的onDestroy方法回调
    mInstrumentation.callActivityOnDestroy(r.activity);
    return r;
}

配置变化时会回调onRetainNonConfigurationInstance方法,将mViewModelStore保存在NonConfigurationInstances,同时performDestroyActivity时将NonConfigurationInstances记录到ActivityClientRecord中去。

小结:VM -> ViewModelStore->NonConfigurationInstances -> ActivityThread 中的 ActivityClientRecord。中间通过 activity 来处理保存、恢复。

onSaveInstanceState和ViewModel

两者在数据处理方面的不同:

  • ViewModel最终是交给 ActivityThread 中的 ActivityClientRecord 暂存的,进程被回收ViewModel 也就被回收。
  • ViewModel能恢复因配置变更导致重建的数据,并不能恢复因资源限制(比如内存限制,电量限制等)进程杀死导致的数据恢复。
  • onSaveInstanceState 可以保存因系统限制进程被杀或者配置变化的数据,这些数据存储在内存中,而不是硬盘上,由android 系统来管理。
  • ViewModel支持保存大量和复杂的数据,比如说RecyclerView的data(ActivityThread持有)。

SavedStateHandle

ViewModel 通过SavedStateHandle类处理数据与onSaveInstanceState()的方式没有任何区别

class MyViewModel(private val saveStateHandle: SavedStateHandle) : ViewModel() {
    val info = saveStateHandle.get<String>("KEY_INFO") // 取值
    val infoFlow = saveStateHandle.getStateFlow("KEY_INFO", "") // 以 flow 形式

    fun setInfo(info: String) { // 设置值
        saveStateHandle.set("KEY_INFO", info)
    }
}

//通过AbstractSavedStateViewModelFactory或者SavedStateViewModelFactory创建ViewModel对象:
private val viewModel by lazy {
    ViewModelProvider(
        this, SavedStateViewModelFactory(application, this)
    )[MyViewModel::class.java]
}

比如在Fragment中是如何save的?

// 触发销毁时
void performSaveInstanceState(Bundle outState) {
    ......
    onSaveInstanceState(outState);
    mSavedStateRegistryController.performSave(outState);
    ......
}

//也是保存到bundle里
void performSave(@NonNull Bundle outBundle) {
    Bundle components = new Bundle();
    if (mRestoredState != null) {
        components.putAll(mRestoredState);
    }
    for (Iterator<Map.Entry<String, SavedStateProvider>> it =
            mComponents.iteratorWithAdditions(); it.hasNext(); ) {
        Map.Entry<String, SavedStateProvider> entry1 = it.next();
        components.putBundle(entry1.getKey(), entry1.getValue().saveState());
    }
    outBundle.putBundle(SAVED_COMPONENTS_KEY, components);
}

最后

分享一下这段时间精心整理收集的·关于Android Framework的知识脑图以及源码学习手册文档! 希望能够帮助大家夯实底层原理、源码解析等核心技术点,掌握普通开发者,难以触及的复杂系统问题设计方案,冲刺一波大厂。

有需要的朋友可以直接扫描下方二维码免费领取!!!

Android Hanlder 消息机制知识点汇总_第1张图片

《Android Framework源码开发揭秘》

第一章 系统启动流程分析

  • 第一节 Android启动概括
  • 第二节 init.rc解析
  • 第三节 Zygote
  • 第四节 面试题
    Android Hanlder 消息机制知识点汇总_第2张图片

第二章 跨进程通信IPC解析

  • 第一节 Service还可以这么理解
  • 第二节 Binder基础
  • 第三节 Binder应用
  • 第四节 AIDL应用(上)
  • 第五节 AIDL应用(下)
  • 第六节 Messenger原理及应用
  • 第七节 服务端回调
  • 第八节 获取服务(IBinder)
  • 第九节 Binder面试题全解析
    Android Hanlder 消息机制知识点汇总_第3张图片

第三章 Handler源码解析

  • 第一节 源码分析
  • 第二节 难点问题
  • 第三节 Handler常问面试题Android Hanlder 消息机制知识点汇总_第4张图片

第四章 AMS源码解析

  • 第一节 引言
  • 第二节 Android架构
  • 第三节 通信方式
  • 第四节 系统启动系列
  • 第五节 AMS
  • 第六节 AMS面试题解析Android Hanlder 消息机制知识点汇总_第5张图片

第五章 WMS源码解析

  • 第一节 WMS与activity启动流程
  • 第二节 WMS绘制原理
  • 第三节 WMS角色与实例化过程
  • 第四节 WMS工作原理Android Hanlder 消息机制知识点汇总_第6张图片

第六章 Surface源码解析

  • 第一节 创建流程及软硬件绘制
  • 第二节 双缓冲及Surface View解析
  • 第三节 Android图形系统综述Android Hanlder 消息机制知识点汇总_第7张图片

第七章 基于Android12.0的SurfaceFlinger源码解析

  • 第一节 应用建立和SurfaceFlinger的沟通桥梁
  • 第二节 SurfaceFlinger的启动和消息队列处理机制
  • 第三节 SurfaceFlinger之VSyns(上)
  • 第四节 SurfaceFlinger之VSyns(中)
  • 第五节 SurfaceFlinger之VSyns(下)Android Hanlder 消息机制知识点汇总_第8张图片

第八章 PKMS源码解析

  • 第一节 PKMS调用方式
  • 第二节 PKMS启动过程分析
  • 第三节 APK的扫描
  • 第四节 APK的安装
  • 第五节 PKMS之权限扫描
  • 第六节 静默安装
  • 第七节 requestPermissions源码流程解析
  • 第八节 PKMS面试题Android Hanlder 消息机制知识点汇总_第9张图片

第九章 InputManagerService源码解析

  • 第一节 Android Input输入事件处理流程(1)
  • 第二节 Android Input输入事件处理流程(2)
  • 第三节 Android Input输入事件处理流程(3)Android Hanlder 消息机制知识点汇总_第10张图片

第十章 DisplayManagerService源码解析

  • 第一节 DisplayManagerService启动
  • 第二节 DisplayAdepter和DisplayDevice的创建
  • 第三节 DMS部分亮灭屏流程
  • 第四节 亮度调节
  • 第五节 Proximity Sensor灭屏原理
  • 第六节 Logical Display和Physical Display配置的更新Android Hanlder 消息机制知识点汇总_第11张图片
有需要的朋友可以直接扫描下方二维码免费领取!!!
Android Hanlder 消息机制知识点汇总_第12张图片

你可能感兴趣的:(android,spring)