savedInstanceState和 fragment.setRetainInstance以及 viewmodel的区别

栏目: Android · 发布时间: 7年前

内容简介:以默认activity的配置 在屏幕旋转的时候,一般activty都会被重建,以这个情况为例子来说明 Bundle savedInstanceState 和 fragment.setRetainInstance 以及 viewmodel的区别作者github :Bundle savedInstanceState 和 fragment.setRetainInstance 以及 viewmodel(viewModel = ViewModelProviders.of(this).get(UserProfileV

以默认activity的配置 在屏幕旋转的时候,一般activty都会被重建,以这个情况为例子来说明 Bundle savedInstanceState 和 fragment.setRetainInstance 以及 viewmodel的区别

0. 转载请注明原文出处

作者github : github.com/zjw-swun 欢迎相互关注

1. 为什么要把这3个放在一块说

Bundle savedInstanceState 和 fragment.setRetainInstance 以及 viewmodel(viewModel = ViewModelProviders.of(this).get(UserProfileViewModel.class);用法而不是自己new的那种),都具备一种功能,就是当 屏幕旋转的时候( 以默认activity的配置前提),都能保存一些要被销毁掉的activity中的一些数据(如editext文本,以及recyclerView的滑动位置等),那么这3个有什么区别吗,会不会因为我们不知道原理而踩坑,下文给出答案。

2. 结论

  1. Bundle savedInstanceState 中的数据是由系统进程进行存储的,它能存储的 数据容量大小有限 (例如intent中如果传输Bundle内容过大会出现异常),但是比如自己app因为手机内存不足而杀掉进程的话,可以 能够 利用该方式进行数据还原 2. fragment.setRetainInstance 以及 viewmodel (viewModel = ViewModelProviders.of(this).get(UserProfileViewModel.class);用法而不是自己new的那种)的原理是一样的,都是利用,Activity类的 NonConfigurationInstances 类在app进程中进行保存的,它能存储 数据容量比Bundler savedInstanceState 方式要大 ,但是比如自己app因为手机内存不足而杀掉进程的话,则 不能 用该方式进行数据还原

3. 部分源码分析

以下以activity类中NonConfigurationInstances类如何在屏幕旋转的时候( 以默认activity的配置前提)如何存储并恢复NonConfigurationInstances对象为例,剖析原理 以下截图以及截图中的代码api版本为28,运行环境官方api 28的模拟器上 测试代码就不贴了很简单, 先贴一下debug断点列表,有兴趣可以试试,至于如何debug app以及debug系统进程,不知道的朋友可以看一下我另一篇文章 https://www.imooc.com/article/21992 废话不多说 放图

savedInstanceState和 fragment.setRetainInstance以及 viewmodel的区别

然后看重建activity时候的断点(截图中截的是被杀死的activity 走到ondestroy的时候)

savedInstanceState和 fragment.setRetainInstance以及 viewmodel的区别
这里说明一下上一个activty先走ondrstroy 然后才重建新的activity这里和activity跳转做一个区分,然后从上图中可以发现被杀死的activity 走到ondestroy的时候中的 r 和重建时候传入的参数 r

(ActivityThread类中的ActivityClientRecord类型)是同一个对象,看看一下这个ActivityClientRecord类的代码

static final class ActivityClientRecord {
       //...不重要参数
        Activity.NonConfigurationInstances lastNonConfigurationInstances;
        //...不重要参数;
        }
复制代码

这就是核心的原理代码了,那么为什么说是存储在app进程中呢,根据断点列表你会发现涉及到一个关键类叫做 ActivityRelaunchItem 这个类

savedInstanceState和 fragment.setRetainInstance以及 viewmodel的区别
这个类的 mActivityClientRecord 就是app进程存储的那个 r 了,这个 r 里面包含了 lastNonConfigurationInstances ,当activty切换的时候,系统进程通过binder机制通知app进程的client对象也就是activityThread间接调用 preExecute 方法,进行保存,然后当重建activity的时候再系统进程通过binder机制通知app进程的client对象也就是activityThread(由activityThread.h发送 H.RELAUNCH_ACTIVITY 消息通过handler机制)间接调用 execute 方法 下图是activity重建时候调用 execute

函数调用栈截图

savedInstanceState和 fragment.setRetainInstance以及 viewmodel的区别
重建activty后进行attach把上个被杀死的activity存下来的 rlastNonConfigurationInstances

再设置给新activity

中间省略的步骤虽然多,但是根据断点列表走下来其实很清楚的。

授人以鱼不如授人以渔

对于如何调试app进程和系统进程, www.imooc.com/article/219… 一文中有具体操作,但是涉及到 binder 类是如何进行 transact 发消息给别的进程以及如何 execTransact 处理别的进程消息 的c++层的原理并没有给出解答,这里推荐一篇博客 blog.csdn.net/innost/arti… 讲解的还算不错。


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Web Design Handbook

Web Design Handbook

Baeck, Philippe de 编 / 2009-12 / $ 22.54

This non-technical book brings together contemporary web design's latest and most original creative examples in the areas of services, media, blogs, contacts, links and jobs. It also traces the latest......一起来看看 《Web Design Handbook》 这本书的介绍吧!

HTML 压缩/解压工具
HTML 压缩/解压工具

在线压缩/解压 HTML 代码

随机密码生成器
随机密码生成器

多种字符组合密码

HTML 编码/解码
HTML 编码/解码

HTML 编码/解码