Android 个人笔记 — Activity常见问题

325 阅读3分钟

个人笔记

Android — Activity常见问题

Android 提供与用户进行交互的可视化页面容器

一.生命周期

  • onCreate() —— 创建
  • onStart() —— 启动 可见
  • onResume() —— 恢复 可交互
  • onPause() —— 暂停 不可交互
  • onStop() —— 停止 不可见
  • onDestroy() —— 销毁

生命周期常见问题

  1. Activity从创建到销毁生命周期调用顺序
onCreate() -> onStart() -> onResume() -> onPause() -> onStop() -> onDestroy()
  1. 从A Activity 跳转 B Activity 生命周期的调用
A onPause() -> B onCreate() -> B onStart() -> B onResume() -> A onStop()
  1. 接2 从 B 回退到 A 生命周期的调用
B onPause() -> A onStart() -> A onResume() -> B onStop() -> B onDestroy()
  1. 接2 如果A 跳转 B 时,调用 finish() 生命周期的调用
A onPause() -> B onCreate() -> B onStart() -> B onResume() -> A onStop() -> A onDestroy()
  1. 接4 如果此时 从 B Activity 回退 会发生什么 生命周期的调用 回退时会直接退出应用
B onPause() -> B onStop() -> B onDestroy()

二.启动模式

  • Standard 标准模式
    • Activity的默认启动模式
    • Activity启动时系统都会创建一个对应实例,并置入当前任务栈中
    • 无论是否存在相同实例,都将创建一个新的实例,因此一个栈中可能有多个相同实例
  • SingeleTop 栈顶复用模式
    • 该模式下启动Activity时,若当前任务栈栈顶存在该Activity的实例,则复用该实例
    • 若当前任务栈中不存在该实例或实例不在栈顶时,系统会创建一个新的实例置入任务栈中
    • 使用方式
    1. AndroidManifest文件中指定launchMode
    <activity android:name=".MainActivity"
            android:launchMode="singleTop"/>
    
    1. 在Java代码中设置Intent标志位指定 优先级高于Manifest文件指定
    Intent intent = new Intent(MainActivity.this, SecondActivity.class);
    intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
    
  • SingleTask 栈内复用模式
    • 该模式下启动Activity时,若当前栈中存在该Activity实例时,则复用该实例
    • 同时,复用该实例时,会将在它之上的所有Activity实例全部出栈
    • 会进行任务栈匹配,通过taskAffinity属性来指定任务栈,默认为程序包名
      • 若任务栈不存在,将新建任务栈并将Activity实例置入
      • 若任务栈存在,则判断是否存在Acitvity实例,存在则调用onNewIntent()复用,不存在则新建实例
    • 使用方式
    1. AndroidManifest文件中指定launchMode
    <activity android:name=".MainActivity"
            android:launchMode="singleTask"
            android:taskAffinity="com.worriesl.launch"/>
    
    1. 在Java代码中设置Intent标志位指定 优先级高于Manifest文件指定
    Intent intent = new Intent(MainActivity.this, SecondActivity.class);
    intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    
  • SingleInstances 单实例模式
    • 该模式下启动Activity时,首先查找系统中是否存在该实例
      • 存在,则调用onNewIntent()复用该实例
      • 不存在,则新建一个任务栈,并创建一个新的Activity实例置入栈中
    • 使用方式
    1. AndroidManifest文件中指定launchMode
    <activity android:name=".MainActivity"
            android:launchMode="singleInstances"
            android:taskAffinity="com.worriesl.launch"/>
    

三.Activity 状态

onSaveInstanceState()

onSaveInstanceState()用于保存一些临时的状态,通常在Activity停止时调用该方法,但仅限于系统停止Activity时,如按下Home键回到首页内存不足回收Activity等,像通过回退键finish()等主动销毁Activity时,不会调用该方法

onSaveInstanceState() 中将需要保存的状态以键值对的形式保存在Bundle对象中

该方法的调用时机在 API < 28 之前,通常是在onPause()onStop()
而在 API >= 28之后,调用时机在onStop()之后

onRestoreInstanceState()

onRestoreInstanceState()用于在重建被销毁的Activity时,恢复在onSaveInstanceState()保存的数据

但并不是所有情况下都会调用onRestoreInstanceState(),像按下Home键按下锁屏键等情况下不会调用该方法,而像屏幕旋转系统回收Activity,重建时则会调用该方法

同时在onCreate()中同样可以获取到onSaveInstanceState()中保存的Bundle,所以也可以在onCreate()中恢复保存数据,但需要对Bundle进行判空,因为不调用onSaveInstanceState()时,Bundle为空

onRestoreInstanceState()调用时机在onStart()之后

onConfigurationChanged()

上面提到,当屏幕旋转时,会分别调用onSaveInstanceState() 和 onRestoreInstanceState() 进行保存和恢复数据

但当在Manifest文件中设置

android:configChanges="orientation|screenSize"

恢复数据时则不会调用onRestoreInstanceState()而是调用onConfigurationChanged()

android:configChanges还支持系统字体大小、地区、外接键盘等变化时的监听