模拟Android内存不足 activity回收 值保存 状态恢复

6,439 阅读5分钟

作者简介

微信公众号(高质量文章推送):陈博易
作者:陈博易
声明:本文是个人原创,未经允许请勿转载
商业合作请在微信公众号回复:联系方式

案例演示
案例演示

前言


1.我记得我实习的那会,面试官问我关于acitivity的现场如何恢复,我当时也就知道保存和取值的方法,今天就当复习了。

2.同时也希望大家帮小编一起分享给其他人,让小编的文章可以让更多人看到

环境以及工具


  1. Android项目:AndroidStudio3.0

整体步骤


  1. Activity中如何保存值,如何状态恢复

详细步骤


1. Activity中保存值,状态恢复

当Andriod系统由于某种原因回收了activity,这时会调用activity的onSaveInstanceState方法保存值

   @Override
    protected void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        //存值
        outState.putString("test", "test");
        Log.d("tag", "onSaveInstanceState:test ");
    }

当Andriod重新创建activity,这时会调用activity的onRestoreInstanceState或者onCreate方法取出保存值

 @Override
    protected void onRestoreInstanceState(Bundle savedInstanceState) {
        super.onRestoreInstanceState(savedInstanceState);
        //拿值,方式1
        String test = savedInstanceState.getString("test");
        Log.d("tag", "onRestoreInstanceState" + test);
    }
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main2);
        if (savedInstanceState != null) {
            //拿值,方式2
            String test = savedInstanceState.getString("test");
            Log.d("tag", "onRestoreInstanceState" + test);
        }
    }

核心步骤解读


1. 模拟当前应用被系统回收

进入开发者选项,选中不保留活动。
开启选项后,启动目标程序页面,用Home键返回桌面,稍候几秒再次点击启动目标程序。
测试完毕后,最好将刚刚选中的不保留活动的选项恢复如初。

选中不保留活动
选中不保留活动

知识盲点梳理


1. 何时回收当前应用activity

除了在栈顶的Activity,其他的Activity都有可能在内存不足的时候被系统回收,一个Activity越处于栈底,被回收的可能性就越大。

2. 何时onSaveInstanceState被执行

当某个activity变得“容易”被系统销毁时,该activity的onSaveInstanceState就会被执行,除非该activity是被用户主动销毁的,例如当用户按BACK键(手机下方的返回键)的时候。

分为以下几种情况:

  • 从第一个界面跳转到第二个界面,第一个界面就会执行onSaveInstanceState
  • 按下home键,运行多个其他程序,这时系统不确定会不会将该activity销毁,所以会执行onSaveInstanceState方法保存值。
  • 关闭手机屏幕时
  • 屏幕方向切换时,例如从竖屏切换到横屏时。(前提是androidMenifest.xml中对应activity标签没有配置)
     <!--防止系统配置改变,重新创建Activity。常见场合:弹出软键盘、屏幕旋转-->
          <activity
              android:name=".Main2Activity"
              android:configChanges="orientation|keyboardHidden|screenSize"></activity>
    3. 为什么我们的UI界面的值不用我们自己保存也可以自动保存,状态恢复呢?
  1. 开发者只需要为这些控件指定一个唯一的ID(通过设置android:id属性即可),剩余的事情就可以自动完成了。如果没有为控件指定ID,则这个控件就不会进行自动的数据保存和恢复操作。(不相信的可以试试看)
  2. Android应用框架中定义的几乎所有的UI控件都恰当的实现了onSaveInstanceState()方法,因此当Activity被摧毁和重建时,这些UI控件会自动保存和恢复状态数据。
4. 为什么onSaveInstanceState 执行时机会在onStop之前呢?

小编也是写文章的时候再思考这个onSaveInstanceState是在什么具体时间被条用的,所以小编就开始深入跟进源码了


看到这里小编还是没看到什么东西。
只是知道了AppCompatActivity FragmentActivity SupportActivity 分别初始化了父类的onSaveInstanceState,关键这个onSaveInstanceState是时候被调用呢?
又发现了activity中的onSaveInstanceState被一个public的方法调用了。

终于到了最想看到的方法了。也不知道什么原因无法看到哪里调了performSaveInstanceState方法,如果有高人看到指点指点了。给我评论下,应该自己的源码导入姿势不大对吧。

接下来的比较复杂,涉及到Activity启动流程在里面,本人目前也不是很清楚的,但是我比较清楚的是Activity的启动流程涉及ActivityThread与ActivityManagerService之间的通讯,实际上acitivty的启动分为应用进程端的启动和SystemServer服务进程端的启动的,而在应用进程端靠的是Intrumentation来执行一些方法的。
ActivityThread中的一些方法看着好像有点认识。和生命周期的一些方法有点像,因为perform带有执行的意思。

核心的方法到了,从这里就可以看出onSaveInstanceState方法是在onStop方法之前执行的。

private void performStopActivityInner(ActivityClientRecord r,
            StopInfo info, boolean keepShown, boolean saveState, String reason) {
             ...........................省去n行代码
            // Next have the activity save its current state and managed dialogs...
            //下一步将保存当前activity的状态
            if (!r.activity.mFinished && saveState) {//activity还没finish并且save为true
                if (r.state == null) {
                    callCallActivityOnSaveInstanceState(r);//调用callCallActivityOnSaveInstanceState
                }
            }
    }

这里发现 mInstrumentation这个应用进程端的操作类调用了callActivityOnSaveInstanceState

答案好像出来了,这里就是activity.performSaveInstanceState

这里是不是就和前面的activity的performSaveInstanceState首尾呼应了呢。

总结

Android源码解析请参考这个大神的,小编的水平还是没到这个水平的。

blog.csdn.net/qq_23547831…

个人相关教程

各种大佬推荐的编程视频资源分享
postman使用 Android java后端 接口调试工具
Android抓包 Charles http接口调试
消息推送 Android java后端集成小米推送
如何导入简单的java项目-IntelliJ IDEA

请关注我(高质量文章推送)

关注微信公众号:走向全栈工程师

长按二维码“识别”关注或者扫一扫
长按二维码“识别”关注或者扫一扫