编程进阶网编程进阶网
  • 基础组成体系
  • 程序编程原理
  • 异常和IO系统
  • 六大设计原则
  • 设计模式导读
  • 创建型设计模式
  • 结构型设计模式
  • 行为型设计模式
  • 设计模式案例
  • 面向对象思想
  • 基础入门
  • 高级进阶
  • JVM虚拟机
  • 数据集合
  • Java面试题
  • C语言入门
  • C综合案例
  • C标准库
  • C语言专栏
  • C++入门
  • C++综合案例
  • C++专栏
  • HTML
  • CSS
  • JavaScript
  • 前端专栏
  • Swift
  • iOS入门
  • 基础入门
  • 开源库解读
  • 性能优化
  • Framework
  • 方案设计
  • 媒体音视频
  • 硬件开发
  • Groovy
  • 常用工具
  • 大厂面试题
  • 综合案例
  • 网络底层
  • Https
  • 网络请求
  • 故障排查
  • 专栏
  • 数组
  • 链表
  • 栈
  • 队列
  • 树
  • 递归
  • 哈希
  • 排序
  • 查找
  • 字符串
  • 其他
  • Bash脚本
  • Linux入门
  • 嵌入式开发
  • 代码规范
  • Markdown
  • 开发理论
  • 开发工具
  • Git管理
  • 百宝箱
  • 开源协议
  • 技术招聘
  • 测试经验
  • 职场提升
  • 技术模版
  • 关于我
  • 目标清单
  • 学习框架
  • 育儿经验
  • 我的专栏
  • 底层能力
  • 读书心得
  • 随笔笔记
  • 职场思考
  • 中华历史
  • 经济学故事
  • 基础组成体系
  • 程序编程原理
  • 异常和IO系统
  • 六大设计原则
  • 设计模式导读
  • 创建型设计模式
  • 结构型设计模式
  • 行为型设计模式
  • 设计模式案例
  • 面向对象思想
  • 基础入门
  • 高级进阶
  • JVM虚拟机
  • 数据集合
  • Java面试题
  • C语言入门
  • C综合案例
  • C标准库
  • C语言专栏
  • C++入门
  • C++综合案例
  • C++专栏
  • HTML
  • CSS
  • JavaScript
  • 前端专栏
  • Swift
  • iOS入门
  • 基础入门
  • 开源库解读
  • 性能优化
  • Framework
  • 方案设计
  • 媒体音视频
  • 硬件开发
  • Groovy
  • 常用工具
  • 大厂面试题
  • 综合案例
  • 网络底层
  • Https
  • 网络请求
  • 故障排查
  • 专栏
  • 数组
  • 链表
  • 栈
  • 队列
  • 树
  • 递归
  • 哈希
  • 排序
  • 查找
  • 字符串
  • 其他
  • Bash脚本
  • Linux入门
  • 嵌入式开发
  • 代码规范
  • Markdown
  • 开发理论
  • 开发工具
  • Git管理
  • 百宝箱
  • 开源协议
  • 技术招聘
  • 测试经验
  • 职场提升
  • 技术模版
  • 关于我
  • 目标清单
  • 学习框架
  • 育儿经验
  • 我的专栏
  • 底层能力
  • 读书心得
  • 随笔笔记
  • 职场思考
  • 中华历史
  • 经济学故事
  • 1.1App启动流程梳理
  • 1.2ActivityThread分析
  • 1.3Context设计思想
  • 2.1Activity基础介绍
  • 2.2Activity启动流程
  • 2.3Activity布局创建
  • 2.4Activity布局绘制
  • 2.5Service基础介绍
  • 2.6Service启动流程
  • 2.7Receiver广播基础
  • 2.8Receiver深入原理
  • 2.9ContentProvider分析
  • 2.10Fragment实践
  • 2.11Intent深入思考
  • 3.1Paint和Canvas
  • 3.2View的绘制基础
  • 3.3onMeasure流程设计
  • 3.4onLayout流程设计
  • 3.5onDraw流程设计
  • 3.6View工作原理
  • 3.7View刷新设计流程
  • 3.8自定义View控件
  • 3.9自定义ViewGroup控件
  • 4.1Handler基础使用
  • 4.2消息机制流程分析
  • 4.3Handler深度解析
  • 4.4Message深度理解
  • 4.5MessageQueue解析
  • 4.6Looper深度解析
  • 4.7理解Handler同步屏障
  • 4.8ThreadLocal分析
  • 4.9ThreadLocal场景
  • 5.1View事件设计思考
  • 5.2View滑动冲突处理
  • 5.3View事件源码分析
  • 5.4View事件总结案例
  • 6.1DecorView设计思想
  • 6.2视图的载体View
  • 6.3视图管理者Window
  • 6.4窗口管理服务WMS
  • 6.5布局解析者Inflater
  • 7.1AsyncTask深入介绍
  • 7.2HandlerThread设计
  • 7.3IntentService设计
  • 8.1IPC通信方式介绍
  • 8.2AIDL进程间通信
  • 8.7Binder通信机制设计
  • /zh/android/basic/9.1注解设计思想和原理.html
  • 9.2APT技术设计详解
  • 9.3APT多种案例实践

2.1Activity基础介绍

目录介绍

  • 01.Activity生命周期
    • 1.1 生命周期方法说明
    • 1.2 特殊情况下生命周期
    • 1.3 Activity三种运行状态
    • 1.4 App切换到后台分析
  • 02.Activity的启动模式
    • 2.1 启动模式的类别
    • 2.2 启动模式的结构——栈
    • 2.3 标准模式(standard)
    • 2.4 栈顶复用模式(singleTop)
    • 2.5 栈内复用模式(singleTask)
    • 2.6 单例模式(singleInstance)
    • 2.7 Activity的Flags
  • 03.特殊情况栈交互
  • 04.Activity异常情况
    • 4.1 Activity异常生命周期
    • 4.2 后台Activity被异常回收

01.Activity生命周期

1.1 生命周期方法说明

  • 在正常情况下,一个Activity从启动到结束会以如下顺序经历整个生命周期:
    • (1) onCreate():当 Activity 第一次创建时会被调用。这是生命周期的第一个方法。在这个方法中,可以做一些初始化工作,比如调用setContentView去加载界面布局资源,初始化Activity所需的数据。当然也可借助onCreate()方法中的Bundle对象来回复异常情况下Activity结束时的状态(后面会介绍)。
    • (2) onRestart():表示Activity正在重新启动。一般情况下,当当前Activity从不可见重新变为可见状态时,onRestart就会被调用。这种情形一般是用户行为导致的,比如用户按Home键切换到桌面或打开了另一个新的Activity,接着用户又回到了这个Actvity。(关于这部分生命周期的历经过程,后面会介绍。)
    • (3) onStart(): 表示Activity正在被启动,即将开始,这时Activity已经出现了,但是还没有出现在前台,无法与用户交互。这个时候可以理解为Activity已经显示出来,但是我们还看不到。
    • (4) onResume():表示Activity已经可见了,并且出现在前台并开始活动。需要和onStart()对比,onStart的时候Activity还在后台,onResume的时候Activity才显示到前台。
    • (5) onPause():表示 Activity正在停止,仍可见,正常情况下,紧接着onStop就会被调用。在特殊情况下,如果这个时候快速地回到当前Activity,那么onResume就会被调用(极端情况)。onPause中不能进行耗时操作,会影响到新Activity的显示。因为onPause必须执行完,新的Activity的onResume才会执行。
    • (6) onStop():表示Activity即将停止,不可见,位于后台。可以做稍微重量级的回收工作,同样不能太耗时。
    • (7) onDestroy():表示Activity即将销毁,这是Activity生命周期的最后一个回调,可以做一些回收工作和最终的资源回收。
  • 在平常的开发中,我们经常用到的就是 onCreate()和onDestroy(),做一些初始化和回收操作。

1.2 特殊情况下生命周期

  • 第一种情况,销毁当前的Activity后重建,这种也尽量避免。
    • 在横竖屏切换的过程中,会发生Activity被销毁并重建的过程。在了解这种情况下的生命周期时,首先应该了解这两个回调:onSaveInstanceState和onRestoreInstanceState。
    • 在Activity由于异常情况下终止时,系统会调用onSaveInstanceState来保存当前Activity的状态。这个方法的调用是在onStop之前,它和onPause没有既定的时序关系,该方法只在Activity被异常终止的情况下调用。
    • 当异常终止的Activity被重建以后,系统会调用onRestoreInstanceState,并且把Activity销毁时onSaveInstanceState方法所保存的Bundle对象参数同时传递给onRestoreInstanceState和onCreate方法。
    • 因此,可以通过onRestoreInstanceState方法来恢复Activity的状态,该方法的调用时机是在onStart之后。其中onCreate和onRestoreInstanceState方法来恢复Activity的状态的区别: onRestoreInstanceState回调则表明其中Bundle对象非空,不用加非空判断。onCreate需要非空判断。建议使用onRestoreInstanceState。
  • 第二种情况,当前的Activity不销毁,设置Activity的属性。
    • 比如视频播放器就经常会涉及屏幕旋转场景。可以通过在AndroidManifest文件的Activity中指定如下属性:
    <activity
        android:name=".activity.VideoDetailActivity"
        android:configChanges="orientation|keyboardHidden|screenSize"
        android:screenOrientation="portrait"/>
    • 来避免横竖屏切换时,Activity的销毁和重建,而是回调了下面的方法:
    //重写旋转时方法,不销毁activity
    @Override
    public void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);
    }
  • 资源内存不足导致优先级低的Activity被杀死
    • Activity优先级的划分和下面的Activity的三种运行状态是对应的。
    • (1) 前台Activity——正在和用户交互的Activity,优先级最高。
    • (2) 可见但非前台Activity——比如Activity中弹出了一个对话框,导致Activity可见但是位于后台无法和用户交互。
    • (3) 后台Activity——已经被暂停的Activity,比如执行了onStop,优先级最低。
    • 当系统内存不足时,会按照上述优先级从低到高去杀死目标Activity所在的进程。我们在平常使用手机时,能经常感受到这一现象。这种情况下数组存储和恢复过程和上述情况一致,生命周期情况也一样。

1.3 Activity三种运行状态

  • ①Resumed(活动状态)
    • 又叫Running状态,这个Activity正在屏幕上显示,并且有用户焦点。这个很好理解,就是用户正在操作的那个界面。
  • ②Paused(暂停状态)
    • 这是一个比较不常见的状态。这个Activity在屏幕上是可见的,但是并不是在屏幕最前端的那个Activity。比如有另一个非全屏或者透明的Activity是Resumed状态,没有完全遮盖这个Activity。
  • ③Stopped(停止状态)
    • 当Activity完全不可见时,此时Activity还在后台运行,仍然在内存中保留Activity的状态,并不是完全销毁。这个也很好理解,当跳转的另外一个界面,之前的界面还在后台,按回退按钮还会恢复原来的状态,大部分软件在打开的时候,直接按Home键,并不会关闭它,此时的Activity就是Stopped状态。

1.4 App切换到后台分析

  • app切换到后台,当前activity会走onDestroy方法吗?
    • 不会走onDestroy方法,会先后走onPause和onStop方法。
  • 一般在onStop方法里做什么?
    • 比如。写轮播图的时候,会在onStop方法里写上暂停轮播图无限轮播,在onStart方法中会开启自动无限轮播。
    • 再比如,写视频播放器的时候,当app切换到后台,则需要停止视频播放,也是可以在onStop中处理的。
  • 什么情况会导致app会被杀死,这时候会走onDestroy吗?
    • 系统资源不足,会导致app意外被杀死。应用只有在进程存活的情况下才会按照正常的生命周期进行执行,如果进程突然被kill掉,相当于System.exit(0); 进程被杀死,根本不会走(activity,fragment)生命周期。只有在进程不被kill掉,正常情况下才会执行onDestroy()方法。

02.Activity的启动模式

2.1 启动模式的类别

  • Android提供了四种Activity启动方式:
    • 标准模式(standard)
    • 栈顶复用模式(singleTop)
    • 栈内复用模式(singleTask)
    • 单例模式(singleInstance)

2.2 启动模式的结构——栈

  • Activity的管理是采用任务栈的形式,任务栈采用“后进先出”的栈结构。

2.3 标准模式(standard)

  • 每启动一次Activity,就会创建一个新的Activity实例并置于栈顶。谁启动了这个Activity,那么这个Activity就运行在启动它的那个Activity所在的栈中。
    • 例如:Activity A启动了Activity B,则就会在A所在的栈顶压入一个新的Activity。
  • 特殊场景
    • 特殊情况,如果在Service或Application中启动一个Activity,其并没有所谓的任务栈,可以使用标记位Flag来解决。
      • 解决办法:为待启动的Activity指定FLAG_ACTIVITY_NEW_TASK标记位,创建一个新栈。
    • 应用场景:
      • 绝大多数Activity。如果以这种方式启动的Activity被跨进程调用,在5.0之前新启动的Activity实例会放入发送Intent的Task的栈的顶部,尽管它们属于不同的程序,这似乎有点费解看起来也不是那么合理。
      • 所以在5.0之后,上述情景会创建一个新的Task,新启动的Activity就会放入刚创建的Task中,这样就合理的多了。

2.4 栈顶复用模式(singleTop)

  • 如果需要新建的Activity位于任务栈栈顶,那么此Activity的实例就不会重建,而是重用栈顶的实例。并回调如下方法:
    @Override
    protected void onNewIntent(Intent intent) {
        super.onNewIntent(intent);
    }
    • 由于不会重建一个Activity实例,则不会回调其他生命周期方法。
  • 如果栈顶不是新建的Activity,就会创建该Activity新的实例,并放入栈顶。
  • 应用场景:
    • 在通知栏点击收到的通知,然后需要启动一个Activity,这个Activity就可以用singleTop,否则每次点击都会新建一个Activity。
    • 当然实际的开发过程中,测试妹纸没准给你提过这样的bug:某个场景下连续快速点击,启动了两个Activity。如果这个时候待启动的Activity使用 singleTop模式也是可以避免这个Bug的。
    • 同standard模式,如果是外部程序启动singleTop的Activity,在Android 5.0之前新创建的Activity会位于调用者的Task中,5.0及以后会放入新的Task中。

2.5 栈内复用模式(singleTask)

  • 该模式是一种单例模式,即一个栈内只有一个该Activity实例。
    • 该模式,可以通过在AndroidManifest文件的Activity中指定该Activity需要加载到那个栈中,即singleTask的Activity可以指定想要加载的目标栈。
    • singleTask和taskAffinity配合使用,指定开启的Activity加入到哪个栈中。
    <activity android:name=".Activity1"
    	android:launchMode="singleTask"
    	android:taskAffinity="com.yc.task"
    	android:label="@string/app_name">
    </activity>
  • 关于taskAffinity的值:
    • 每个Activity都有taskAffinity属性,这个属性指出了它希望进入的Task。如果一个Activity没有显式的指明该Activity的taskAffinity,那么它的这个属性就等于Application指明的taskAffinity,如果Application也没有指明,那么该taskAffinity的值就等于包名。
    • 这个也可以不用设置 执行逻辑:
    • 在这种模式下,如果Activity指定的栈不存在,则创建一个栈,并把创建的Activity压入栈内。
    • 如果Activity指定的栈存在,如果其中没有该Activity实例,则会创建Activity并压入栈顶,如果其中有该Activity实例,则把该Activity实例之上的Activity杀死清除出栈,重用并让该Activity实例处在栈顶,然后调用onNewIntent()方法。
    • 对应如下三种情况:
  • 应用场景:
    • 大多数App的主页。对于大部分应用,当我们在主界面点击回退按钮的时候都是退出应用,那么当我们第一次进入主界面之后,主界面位于栈底,以后不管我们打开了多少个Activity,只要我们再次回到主界面,都应该使用将主界面Activity上所有的Activity移除的方式来让主界面Activity处于栈顶,而不是往栈顶新加一个主界面Activity的实例,通过这种方式能够保证退出应用时所有的Activity都能报销毁。
    • 在跨应用Intent传递时,如果系统中不存在singleTask Activity的实例,那么将创建一个新的Task,然后创建SingleTask Activity的实例,将其放入新的Task中。
  • 应用案例
    • 例如浏览器的主界面。不管从多少个应用启动浏览器,只会启动主界面一次,其余情况都会走onNewIntent,并且会清空主界面上面的其他页面。

2.6 单例模式(singleInstance)

  • 作为栈内复用模式(singleTask)的加强版
    • 打开该Activity时,直接创建一个新的任务栈,并创建该Activity实例放入新栈中。一旦该模式的Activity实例已经存在于某个栈中,任何应用再激活该Activity时都会重用该栈中的实例。
  • 应用场景:
    • 呼叫来电界面。这种模式的使用情况比较罕见,在Launcher中可能使用。或者你确定你需要使Activity只有一个实例。建议谨慎使用。

2.7 Activity的Flags

  • Activity的Flags很多,这里介绍集中常用的,用于设定Activity的启动模式。可以在启动Activity时,通过Intent的addFlags()方法设置。
    • (1)FLAG_ACTIVITY_NEW_TASK
    • 其效果与指定Activity为singleTask模式一致。
    • (2)FLAG_ACTIVITY_SINGLE_TOP
    • 其效果与指定Activity为singleTop模式一致。
    • (3)FLAG_ACTIVITY_CLEAR_TOP
    • 具有此标记位的Activity,当它启动时,在同一个任务栈中所有位于它上面的Activity都要出栈。如果和singleTask模式一起出现,若被启动的Activity已经存在栈中,则清除其之上的Activity,并调用该Activity的onNewIntent方法。如果被启动的Activity采用standard模式,那么该Activity连同之上的所有Activity出栈,然后创建新的Activity实例并压入栈中。
  • 同一程序不同的Activity是否可以放在不同的Task任务栈中?
    • 可以的。比如:启动模式里有个singleInstance,可以运行在另外的单独的任务栈里面。用这个模式启动的activity,在内存中只有一份,这样就不会重复的开启。
    • 也可以在激活一个新的activity时候,给intent设置flag,Intent的flag添加FLAG_ACTIVITY_NEW_TASK,这个被激活的activity就会在新的task栈里面

03.特殊情况栈交互

  • 特殊情况——前台栈和后台栈的交互
    • 假如目前有两个任务栈。前台任务栈为AB,后台任务栈为CD,这里假设CD的启动模式均为singleTask,现在请求启动D,那么这个后台的任务栈都会被切换到前台,这个时候整个后退列表就变成了ABCD。当用户按back返回时,列表中的activity会一一出栈。
  • 如下图。
  • 如果不是请求启动D而是启动C,那么情况又不一样,如下图。
  • 调用SingleTask模式的后台任务栈中的Activity,会把整个栈的Activity压入当前栈的栈顶。
    • singleTask会具有clearTop特性,把之上的栈内Activity清除。

04.Activity异常情况

4.1 Activity异常生命周期

  • 虽然前面也说了这个异常的生命周期,但是还是有些疑问?
  • 异常条件会调用什么方法
    • 当非人为终止Activity时,比如系统配置发生改变时导致Activity被杀死并重新创建、资源内存不足导致低优先级的Activity被杀死,会调用 onSavaInstanceState() 来保存状态。该方法调用在onStop之前,但和onPause没有时序关系。
    • 有人会问,onSaveInstanceState()与onPause()的区别,onSaveInstanceState()适用于对临时性状态的保存,而onPause()适用于对数据的持久化保存。
    • 当异常崩溃后App又重启了,这个时候会走onRestoreInstanceState()方法,可以在该方法中取出onSaveInstanceState()保存的状态数据。
  • 什么时候会引起异常生命周期
    • 资源相关的系统配置发生改变或者资源不足:例如屏幕旋转,当前Activity会销毁,并且在onStop之前回调onSaveInstanceState保存数据,在重新创建Activity的时候在onStart之后回调onRestoreInstanceState。其中Bundle数据会传到onCreate(不一定有数据)和onRestoreInstanceState(一定有数据)。
    • 还有中情况是异常导致app崩溃,然后并没有完全杀死进程,重启回到activity页面,也会引起异常生命周期。

4.2 后台Activity被异常回收

  • 后台的Activity被系统回收怎么办?

    • Activity中提供了一个 onSaveInstanceState()回调方法,这个方法会保证一定在活动被回收之前调用,可以通过这个方法来解决活动被回收时临时数据得不到保存的问题。
    • onSaveInstanceState()方法会携带一个Bundle类型的参数,Bundle提供了一系列的方法用于保存数据,比如可以使用putString()方法保存字符串,使用putInt()方法保存整型数据。每个保存方法需要传入两个参数,第一个参数是键,用于后面从 Bundle中取值,第二个参数是真正要保存的内容。
  • 说一下onSaveInstanceState()和onRestoreInstanceState()方法特点?

    • Activity的 onSaveInstanceState()和onRestoreInstanceState()并不是生命周期方法,它们不同于onCreate()、onPause()等生命周期方法,它们并不一定会被触发。
      //保存数据
      @Override
      protected void onSaveInstanceState(Bundle outBundle) {
      	super.onSaveInstanceState(outBundle);
       	outBundle.putBoolean("Change", mChange);
      }
      
      //取出数据
      @Override 
      protected void onRestoreInstanceState(Bundle savedInstanceState) {
      	super.onRestoreInstanceState(savedInstanceState);
      	mChange = savedInstanceState.getBoolean("Change");
      }
      
      //或者在onCreate方法取数据也可以
      //onCreate()方法其实也有一个Bundle类型的参数。这个参数在一般情况下都是null,
      //但是当活动被系统回收之前有通过 onSaveInstanceState()方法来保存数据的话,这个参就会带有之前所保存的全部数据
      protected void onCreate(Bundle savedInstanceState) {
          super.onCreate(savedInstanceState);
          if (savedInstanceState != null) {
              String data = savedInstanceState.getString("data");
          }
      }
  • 什么时候会触发走这两个方法?

    • 当应用遇到意外情况(如:内存不足、用户直接按Home键)由系统销毁一个Activity,onSaveInstanceState() 会被调用。但是当用户主动去销毁一个Activity时,例如在应用中按返回键,onSaveInstanceState()就不会被调用。除非该activity是被用户主动销毁的,通常onSaveInstanceState()只适合用于保存一些临时性的状态,而onPause()适合用于数据的持久化保存。
  • onSaveInstanceState()被执行的场景有哪些?

    • 系统不知道你按下HOME后要运行多少其他的程序,自然也不知道activityA是否会被销毁,因此系统都会调用onSaveInstanceState(),让用户有机会保存某些非永久性的数据。以下几种情况的分析都遵循该原则当用户按下HOME键时
      • 长按HOME键,选择运行其他的程序时
      • 锁屏时
      • 从activity A中启动一个新的activity时
      • 屏幕方向切换时
  • 屏幕旋转时生命周期

    • 屏幕旋转时候,如果不做任何处理,activity会经过销毁到重建的过程。一般这种效果都不是想要的。比如视频播放器就经常会涉及屏幕旋转场景。技术博客大总结
    • 第一种情况:当前的Activity不销毁【设置Activity的android:configChanges="orientation|keyboardHidden|screenSize"时,切屏不会重新调用各个生命周期,只会执行onConfigurationChanged方法】
      <activity
          android:name=".activity.VideoDetailActivity"
          android:configChanges="orientation|keyboardHidden|screenSize"
          android:screenOrientation="portrait"/>
      • 执行该方法
      //重写旋转时方法,不销毁activity
      @Override
      public void onConfigurationChanged(Configuration newConfig) {
      	super.onConfigurationChanged(newConfig);
      }
    • 第二种情况:销毁当前的Activity后重建,这种也尽量避免。【不设置Activity的android:configChanges时,切屏会重新调用各个生命周期,默认首先销毁当前activity,然后重新加载】

1.0.0.3 如何避免配置改变时Activity重建?优先级低的Activity在内存不足被回收后怎样做可以恢复到销毁前状态?

  • 如何避免配置改变时Activity重建
    • 为了避免由于配置改变导致Activity重建,可在AndroidManifest.xml中对应的Activity中设置android:configChanges="orientation|screenSize"。此时再次旋转屏幕时,该Activity不会被系统杀死和重建,只会调用onConfigurationChanged。因此,当配置程序需要响应配置改变,指定configChanges属性,重写onConfigurationChanged方法即可。
    • 使用场景,比如视频播放器横竖屏切换播放视频,就需要设置这种属性。具体可以看我封装的视频播放器库,地址:https://github.com/yangchong211/YCVideoPlayer
  • 优先级低的Activity在内存不足被回收后怎样做可以恢复到销毁前状态
    • 优先级低的Activity在内存不足被回收后重新打开会引发Activity重建。Activity被重新创建时会调用onRestoreInstanceState(该方法在onStart之后),并将onSavaInstanceState保存的Bundle对象作为参数传到onRestoreInstanceState与onCreate方法。因此可通过onRestoreInstanceState(Bundle savedInstanceState)和onCreate((Bundle savedInstanceState)来判断Activity是否被重建,并取出数据进行恢复。但需要注意的是,在onCreate取出数据时一定要先判断savedInstanceState是否为空。
  • 如何判断activity的优先级?技术博客大总结
    • 除了在栈顶的activity,其他的activity都有可能在内存不足的时候被系统回收,一个activity越处于栈底,被回收的可能性越大.如果有多个后台进程,在选择杀死的目标时,采用最近最少使用算法(LRU)。

1.0.0.6 说下Activity的四种启动模式?singleTop和singleTask的区别以及应用场景?任务栈的作用是什么?

  • Activity的四种启动模式
    • standard标准模式:每次启动一个Activity就会创建一个新的实例
    • singleTop栈顶复用模式:如果新Activity已经位于任务栈的栈顶,就不会重新创建,并回调 onNewIntent(intent) 方法
    • singleTask栈内复用模式:只要该Activity在一个任务栈中存在,都不会重新创建,并回调 onNewIntent(intent) 方法。如果不存在,系统会先寻找是否存在需要的栈,如果不存在该栈,就创建一个任务栈,并把该Activity放进去;如果存在,就会创建到已经存在的栈中
    • singleInstance单实例模式:具有此模式的Activity只能单独位于一个任务栈中,且此任务栈中只有唯一一个实例
  • singleTop和singleTask的区别以及应用场景
    • singleTop:同个Activity实例在栈中可以有多个,即可能重复创建;该模式的Activity会默认进入启动它所属的任务栈,即不会引起任务栈的变更;为防止快速点击时多次startActivity,可以将目标Activity设置为singleTop
    • singleTask:同个Activity实例在栈中只有一个,即不存在重复创建;可通过android:taskAffinity设定该Activity需要的任务栈,即可能会引起任务栈的变更;常用于主页和登陆页
  • singleTop或singleTask的Activity在以下情况会回调onNewIntent()
    • singleTop:如果新Activity已经位于任务栈的栈顶,就不会重新创建,并回调 onNewIntent(intent) 方法
    • singleTask:只要该Activity在一个任务栈中存在,都不会重新创建,并回调 onNewIntent(intent) 方法
  • 任务栈的作用是什么?技术博客大总结
    • 它是存放 Activity 的引用的,Activity不同的启动模式,对应不同的任务栈的存放;可通过 getTaskId()来获取任务栈的 ID,如果前面的任务栈已经清空,新开的任务栈ID+1,是自动增长的;首先来看下Task的定义,Google是这样定义Task的:Task实际上是一个Activity栈,通常用户感受的一个Application就是一个Task。从这个定义来看,Task跟Service或者其他Components是没有任何联系的,它只是针对Activity而言的。
  • 同一程序不同的Activity是否可以放在不同的Task任务栈中?
    • 可以的。比如:启动模式里有个Singleinstance,可以运行在另外的单独的任务栈里面。用这个模式启动的activity,在内存中只有一份,这样就不会重复的开启。
    • 也可以在激活一个新的activity时候,给intent设置flag,Intent的flag添加FLAG_ACTIVITY_NEW_TASK,这个被激活的activity就会在新的task栈里面

其他介绍

01.关于博客汇总链接

  • 1.技术博客汇总
  • 2.开源项目汇总
  • 3.生活博客汇总
  • 4.喜马拉雅音频汇总
  • 5.其他汇总

02.关于我的博客

  • github:https://github.com/yangchong211
  • 知乎:https://www.zhihu.com/people/yczbj/activities
  • 简书:http://www.jianshu.com/u/b7b2c6ed9284
  • csdn:http://my.csdn.net/m0_37700275
  • 喜马拉雅听书:http://www.ximalaya.com/zhubo/71989305/
  • 开源中国:https://my.oschina.net/zbj1618/blog
  • 泡在网上的日子:http://www.jcodecraeer.com/member/content_list.php?channelid=1
  • 邮箱:yangchong211@163.com
  • 阿里云博客:https://yq.aliyun.com/users/article?spm=5176.100- 239.headeruserinfo.3.dT4bcV
  • segmentfault头条:https://segmentfault.com/u/xiangjianyu/articles
  • 掘金:https://juejin.im/user/5939433efe88c2006afa0c6e
贡献者: yangchong211
上一篇
1.3Context设计思想
下一篇
2.2Activity启动流程