Activity

Activity是Android四大组件之一,我们在Android设备上打开一款App的时候,看到的界面就是一个Activity,上面承载了很多UI元素,例如:文本框、按钮、输入框 等。

关于Activity,需要掌握一下基本的开发知识:

  • Activity的生命周期

  • Activity的启动模式

  • Activity间的通信方式

  • Activity的状态保存与恢复

  • Activity与Fragment的关系

1、Activity的生命周期

生命周期方法在 界面状态发生变化 的时候 回调,不是开发者手动调用后触发界面状态变化

当我们打开一款App的时候,系统会创建一个界面和用户进行交互,此时会依次回调onCreate、onStart、onResume方法,其中,

onCreate 仅在Activity创建的时候执行一次,此时Activity处于 不可见 的状态;onStart 被回调时,Activity由 不可见变为可见 状态,但仍 未进入前台 和用户进行交互;onResume 被回调时,Activity已经 进入前台,此时用户可以通过Button等UI元素和App进行交互

  • 为什么onStart和onResume不合并成一个函数? 职责分明


注意:

界面 可见状态进入前台 状态的区别

可见状态:可以看到界面,但不一定能和用户进行交互,例如:全屏的界面A被一个消息弹窗遮挡,界面A处于可见状态,但用户无法与之交互

前台:不仅界面可见,还能和用户进行交互,例如上述案例的弹窗


当用户触发弹窗 局部遮挡 界面时,onPause方法被回调,此时Activity处于 失去焦点,但仍然可见 的状态;

当用户 点击Home键,将App切换到后台 时,onStop方法被回调,此时Activity处于 完全不可见 的状态;此时,如果用户 重新将App切回前台,会依次回调 onStop、onRestart、onStart和onResume方法

  • 当用户将Activity切到后台,又切回前台,生命周期如何变化?

当Activity被切到后台时:会依次回调onPause()和onStop()方法

onPause():Activity失去焦点

onStop():Activity完全不可见

当Activity从后台切回前台时:回调顺序为onRestart()、onStart()和onResume()

onRestart(): Activity重新启动

onStart(): Activity变为可见

onResume(): Activity获得焦点,可以与用户交互

  • 当屏幕发生旋转的时候,Activity的生命周期函数被回调的次序?

当Activity发生屏幕旋转时,Activity 会 被销毁,再重建,其生命周期方法被回调的次序为:

Activity 被销毁:onPause->onStop->onDestroy

Activity 被重建:onCreate->onStart->onResume

2、Activity的启动模式

指的是一个Activity应该以 何种启动模式 启动,再跳转到另一个Activity。常见的启动模式有四种:standard、singleTop、singleTask和singleInstance。其中,

  • standard 是 默认 的启动模式,每次启动都会 创建新的Activity实例放入任务栈

  • singleTop 是 栈顶复用模式,如果目标Activity 已在栈顶,则 复用 该Activity;否则,创建新的Activity实例放入任务栈

  • singleTask 是 栈内单例模式,这种模式下任务栈中 只有一个 目标Activity实例。如果目标Activity 不在栈顶,则会将其之上的Activity 出栈;如果没有目标Activity,则创建新的Activity实例放入任务栈

  • singleInstance 是 单实例模式,会 单独创建 一个新的任务栈存放目标Activity

启动模式一般通过两种方式指定:

  • 通过 AndroidMinifest.xml 文件,通过 lanchMode 属性指定

<activity android:name=".MyActivity"
          android:launchMode="singleTop"/>
  • 通过 Intent 的 setFlags 方法设定

Intent intent = new Intent(this, MyActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);

注意:

任务栈:用来 存放Activity实例 的数据结构,通过 taskId 作为 唯一标识 进行管理

taskAffinity:通过该值 确定Activity属于哪个任务栈

onNewIntent

当启动模式为 singleTop 的Activity,若处于 栈顶,会 回调onNewIntent,而不是创建新的实例

当启动模式为 singleTask / singleInstance 时,若任务栈中 已存在 该Activity的实例,也会回调onNewIntent方法;需手动调用setIntent方法更新Activity的Intent对象,否则getIntent获取的仍然是旧的Intent对象

与生命周期方法的关系:onNewIntent -> onRestart -> onStart -> onResume

创建Activity的时候,可以通过设定taskAffinity指定从属的任务栈,其 默认值 包名

taskAffinity 和 singleTask 启动模式联系紧密,其交互如下:

  • 如果查找到 匹配 的taskAffinity:

    • 已在栈中,那么会将该Activity之上的所有其它Activity出栈,确保其在栈中唯一,并且处于栈顶

    • 不在栈中,则会新创建一个 新的Activity实例 放到该任务栈中

  • 如果 没有匹配的taskAffinity,那么会首先创建一个新的任务栈,再将Activity实例放入该任务栈中

<activity android:name=".MainActivity"
          android:launchMode="singleTask"
          android:taskAffinity="com.example.customtask"/>

3、Activity状态保存和恢复
  • onSaveInstanceState:接收一个 Bundle对象 ,以 Key-Value键值对 的形式 保存 数据;在 onCreate 和 onRestoreInstanceState 方法中通过 Bundle对象 恢复

@Override
protected void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);
    outState.putString("key", "value");
    outState.putInt("score", currentScore);
}
​
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    if (savedInstanceState != null) {
        String value = savedInstanceState.getString("key");
        int score = savedInstanceState.getInt("score", 0);
    }
}
​
@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
    super.onRestoreInstanceState(savedInstanceState);
    // 这里的 savedInstanceState 总是非 null
    String someData = savedInstanceState.getString("key");
}

注意:

onSaveInstanceState 在 onStop之后onDestroy 之前 调用

onCreate 中的Bundle对象 可能为空,因为 第一次构建Activity 的时候会回调onCreate方法,此时 Bundle对象为空

onRestoreInstanceState中的Bundle对象 不为空 :Activity被销毁前回调onSaveInstanceState方法,将Bundle对象与Activity进行关联;恢复的时候会检查是否有与之关联的保存状态(Bundle对象),如果有则回调onRestoreInstanceState传入该Bundle对象

  • 通过 ViewModel 保存&恢复数据


4、Fragment

Fragment可以看作是Activity的一个模块化部分,用于展示各种UI元素;并且,具有自己的生命周期方法,但是需要依附于Activity,受Activity生命周期的影响。

  • 生命周期方法

onAttach:Fragment 和 Activity 相关联,是Fragment生命周期的 起点

onCreate:初始化 Fragment,此时还没有UI

onCreateView:创建并返回 Fragment的 层次结构,通过调用 inflate方法 加载布局,返回的是Fragment的 根视图RootView

onViewCreated:在onCreateView之后立即调用,因为前者创建了视图,但没有和父容器进行关联,因此在这里需要通过findViewById等方法,完成视图的初始化操作(通常在这里执行这类操作会 更保险,因为此时 视图已经创建

onActivityCreated:当依附的Activity的onCreate方法完成时调用,此时可以与Activity的视图交互

onStart:Fragment 可见,但未进入前台和用户交互

onResume:Fragment 进入前台,用户可通过Button等UI元素和用户进行交互

onPause:Fragment 被局部遮挡,失去焦点无法和用户进行交互

onStop:Fragment 进入前台,此时界面不可见

onDestroyView:Fragment的视图 被移除

onDestroy:Fragment 被销毁

onDetach:Fragment与Activity 解除关联


注意:

Fragment的生命周期方法,在Activity对应的生命周期方法中调用,因此其 执行次序在Activity对应的方法之后,例如:Fragment的onResume在Activity的onResume之后执行

与Activity生命周期的关联:

  1. 当Activity创建时:Activity onCreate() -> Fragment onAttach() -> Fragment onCreate() -> Fragment onCreateView() -> Fragment onActivityCreated()

  2. 当Activity启动时:Activity onStart() -> Fragment onStart()

  3. 当Activity恢复时:Activity onResume() -> Fragment onResume()

  4. 当Activity暂停时:Activity onPause() -> Fragment onPause()

  5. 当Activity停止时:Activity onStop() -> Fragment onStop()

  6. 当Activity销毁时:Activity onDestroy() -> Fragment onDestroyView() -> Fragment onDestroy() -> Fragment onDetach()


  • Fragment 与 Fragment / Activity 的通信方法?

一般使用 ViewModel 持有数据,在 Fragment 与 Fragment / Activity 之间进行共享比较稳妥

虽然也有使用 EventBus 发送和接收消息,但是这种方式存在: 1、在业务复杂的场景下,容易被滥用,进而导致消息溯源困难;2、以Object对象传递数据,这样使用的时候需要强转数据类型,缺了编译器的类型检查,存在运行时崩溃等风险;3、需要手动注册和释放,存在内存泄漏风险等

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值