【磨叽教程】Android进阶教程之Activity生命周期详解

2024-03-16 23:10

本文主要是介绍【磨叽教程】Android进阶教程之Activity生命周期详解,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

了解Activity生命周期

在这里插入图片描述

在我们正常使用某一个APP的过程中,通常是在这个应用中的不同界面直接来回切换。相对应的Activity实例会在其生命周期的不同状态变换。

Activity提供了很多回调,每个回调都表示个某种状态。比如,我们从打开一个界面到关闭这个界面,Activity就经历了从创建、准备、停止或恢复、停止到销毁一系列的状态变换。

在生命周期回调方法中,我们可以控制用户离开和再次进入 Activity 时 Activity 的行为方式。例如,如果您正构建流媒体视频播放器,当用户切换至另一应用时,您可能要暂停视频或终止网络连接。当用户返回时,您可以重新连接网络并允许用户从同一位置继续播放视频。

换言之,每个回调都可以帮助我们在合适的时间执行正确的任务,并妥善处理转换,这将提升应用的稳健性和性能。

例如,良好的生命周期回调实现有助于防止应用出现以下问题:

  • 当用户在使用应用时接听来电,或切换至另一应用时崩溃。
  • 当用户未主动使用它时,消耗宝贵的系统资源。
  • 当用户离开应用并在稍后返回时,丢失用户的进度。
  • 当屏幕在横向和纵向之间旋转时,崩溃或丢失用户的进度。

本文将详细介绍 Activity 生命周期。首先介绍生命周期概念,接着介绍每个回调:它们执行时内部发生了什么,以及我们应该在执行期间实现什么。然后,简要介绍 Activity 状态与导致进程被系统终止的漏洞之间的关系。更多详情请关注“计算机自学平台”公众号。

Activity 生命周期概念

为了解决Activity与Activity之间的各种转换而保证系统的完整性、性能和正确性,Activity 类提供六个核心回调:onCreate()、onStart()、onResume()、onPause()、onStop()onDestroy()。当创建一个新的Activity时,系统会调用其中每个回调。

在这里插入图片描述
图 1. Activity 生命周期的简化图示。

当用户开始离开 Activity 时,系统会调用方法来销毁该 Activity。在某些情况下,此销毁只是部分销毁;Activity 仍然驻留在内存中(例如当用户切换至另一应用时),并且仍然可以返回到前台。如果用户返回到该 Activity,Activity 会从用户离开时的位置继续运行。
除了少数例外,应用在后台运行时会受到限制,无法启动 Activity。
根据 Activity 的复杂程度,我们在开发的时候不一定要实现Activity的每一个生命周期方法。但是,请务必了解每个方法,并确认我们是在对的时间做对的事情,这非常重要

生命周期回调

本部分介绍 Activity 生命周期中所有回调方法的相关概念及相关信息。

onCreate()

每一个Activity中都必须实现此回调,它会在系统首次创建 Activity 时触发。Activity 会在创建后进入“已创建”状态。在 onCreate() 方法中,我们需执行基本应用启动逻辑,该逻辑在 Activity 的整个生命周期中只应执行一次。
例如,将 Activity 与 ViewModel 相关联,并实例化某些类作用域变量。此方法会接收 savedInstanceState 参数,后者是包含 Activity 先前保存状态的 Bundle 对象。如果 Activity 此前未曾存在,Bundle 对象的值为 null。

以下示例是在onCreate() 方法中执行 Activity 某些基本设置的一些代码,例如声明界面(在 XML 布局文件中定义)、定义成员变量,以及配置某些界面。在这个示例中,系统通过将文件的资源 ID R.layout.main_activity 传递给 setContentView() 来指定 XML 布局文件。

TextView textView;// some transient state for the activity instance
String gameState;@Override
public void onCreate(Bundle savedInstanceState) {// call the super class onCreate to complete the creation of activity like// the view hierarchysuper.onCreate(savedInstanceState);// recovering the instance stateif (savedInstanceState != null) {gameState = savedInstanceState.getString(GAME_STATE_KEY);}// set the user interface layout for this activity// the layout file is defined in the project res/layout/main_activity.xml filesetContentView(R.layout.main_activity);// initialize member TextView so we can manipulate it latertextView = (TextView) findViewById(R.id.text_view);
}// This callback is called only when there is a saved instance that is previously saved by using
// onSaveInstanceState(). We restore some state in onCreate(), while we can optionally restore
// other state here, possibly usable after onStart() has completed.
// The savedInstanceState Bundle is same as the one used in onCreate().
@Override
public void onRestoreInstanceState(Bundle savedInstanceState) {textView.setText(savedInstanceState.getString(TEXT_VIEW_KEY));
}// invoked when the activity may be temporarily destroyed, save the instance state here
@Override
public void onSaveInstanceState(Bundle outState) {outState.putString(GAME_STATE_KEY, gameState);outState.putString(TEXT_VIEW_KEY, textView.getText());// call superclass to save any view hierarchysuper.onSaveInstanceState(outState);
}

除了定义 XML 文件并将其传递给 setContentView()外,您还可以在 Activity 代码中新建 View 对象,并将新建的 View 插入到 ViewGroup 中,以构建视图层次结构。然后,将根 ViewGroup 传递给 setContentView() 以使用该布局。

onCreate() 方法完成执行后,您的 Activity 现在处于“已创建”状态。

onStart()

当 Activity 进入“已开始”状态时,系统会调用此回调。onStart() 调用后使 Activity 将对用户可见,因为应用会为 Activity 进入前台并支持互动做准备。

onStart() 方法会非常快速地完成,并且与“已创建”状态一样,Activity 不会一直处于“已开始”状态。一旦此回调结束,Activity 便会进入“已恢复”状态,系统将调用 onResume() 方法。
onResume()

Activity 会在进入“已恢复”状态时展现在屏幕上,然后系统调用 onResume() 回调。这是应用与用户互动的状态。应用会一直保持这种状态,直到某些事件发生让焦点不在应用上时才会中止。此类事件包括接到来电、跳转到另一个 Activity,或设备屏幕关闭等。

当发生中断事件时,Activity 进入“已暂停”状态,系统调用 onPause() 回调。

如果 Activity 从“已暂停”状态重新返回“已恢复”状态,系统将再次调用 onResume() 方法。因此,我们应在 *onResume()*中实现Activity每次进入该状态时所必需的的所有组件和数据的初始化操作。
然而,在多窗口模式下,即使处于“已暂停”状态,您的 Activity 也可能完全可见。

无论选择在哪个构建事件中执行初始化操作,都请务必使用相应的生命周期事件来释放资源。

onPause()

系统将此方法视为用户将要离开我们的 Activity 的第一个标志(这并不意味着 Activity 会被销毁);此方法表示 Activity 不再位于前台(尽管在用户处于多窗口模式时 Activity 仍然可见)。使用 onPause() 方法暂停或调整当 Activity 处于“已暂停”状态时不应继续(或应有节制地继续)的操作,以及您希望很快恢复的操作。Activity 进入此状态的原因有很多。例如:

onResume() 部分所述,某个事件会中断应用执行。这是最常见的情况。

  • 在 Android 7.0(API 级别
    24)或更高版本中,有多个应用在多窗口模式下运行。无论何时,都只有一个应用(窗口)可以拥有焦点,因此系统会暂停所有其他应用。
  • 有新的半透明 Activity(例如对话框)处于开启状态。只要 Activity 仍然部分可见但并未处于焦点之中,它便会一直暂停。
  • 当 Activity 进入已暂停状态时,与 Activity 生命周期相关联的所有生命周期感知型组件都将收到 ON_PAUSE
    事件。这时,生命周期组件可以停止在组件未位于前台时无需运行的任何功能,例如停止相机预览。

我们还可以使用 onPause() 方法释放系统资源、传感器(例如 GPS)手柄,或当您的 Activity 暂停且用户不需要它们时仍然可能影响电池续航时间的任何资源。然而,正如上文的 onResume() 部分所述,如果处于多窗口模式,“已暂停”的 Activity 仍完全可见。因此,应该考虑使用 onStop() 而非 onPause() 来完全释放或调整与界面相关的资源和操作,以便更好地支持多窗口模式。

onPause() 执行非常简单且快速,而且不一定要有足够的时间来执行保存操作。因此,我们不应使用 onPause() 来保存应用或用户数据、进行网络调用或执行数据库事务。因为在该方法完成之前,此类工作可能无法执行完成该状态就结束了。相反,应在 onStop() 期间执行高负载的关闭操作。

onPause() 方法的完成并不意味着 Activity 离开“已暂停”状态。相反,Activity 会保持此状态直到其恢复或变成对用户完全不可见。如果 Activity 恢复,系统将再次调用 onResume() 回调。如果 Activity 从“已暂停”状态返回“已恢复”状态,系统会让 Activity 实例继续驻留在内存中,并会在系统调用 onResume() 时重新调用该实例。在这种情况下,您无需重新初始化在任何回调方法导致 Activity 进入“已恢复”状态期间创建的组件。如果 Activity 变为完全不可见,系统会调用 onStop()

onStop()

如果Activity 不再对用户可见,说明其已进入“已停止”状态,因此系统将调用 onStop() 回调。例如,当新启动的 Activity 覆盖整个屏幕时。

onStop() 方法中,应用应释放或调整在应用对用户不可见时的无用资源。例如,应用可以暂停动画效果。使用 onStop() 而非 onPause() 可确保与界面相关的工作继续进行,即使用户在多窗口模式下查看您的 Activity 也能如此。

我们还应使用 onStop() 执行 CPU 相对密集的关闭操作。例如,如果您无法找到更合适的时机来将信息保存到数据库,可以在 onStop() 期间执行此操作。以下示例展示了 onStop() 的实现,它将草稿笔记内容保存到持久性存储空间中:

@Override
protected void onStop() {// call the superclass method firstsuper.onStop();// save the note's current draft, because the activity is stopping// and we want to be sure the current note progress isn't lost.ContentValues values = new ContentValues();values.put(NotePad.Notes.COLUMN_NAME_NOTE, getCurrentNoteText());values.put(NotePad.Notes.COLUMN_NAME_TITLE, getCurrentNoteTitle());// do this update in background on an AsyncQueryHandler or equivalentasyncQueryHandler.startUpdate (mToken,  // int token to correlate callsnull,    // cookie, not used hereuri,    // The URI for the note to update.values,  // The map of column names and new values to apply to them.null,    // No SELECT criteria are used.null     // No WHERE columns are used.);
}

请注意,上述代码示例直接使用 SQLite。在实际的开发中建议大家使用 Room,这是一个通过 SQLite 提供抽象层的持久性库。

当Activity 进入“已停止”状态时,Activity 对象会继续驻留在内存中:该对象将维护所有状态和成员信息,但不会附加到窗口管理器。Activity 恢复后,Activity 会重新调用这些信息。我们无需重新初始化在任何回调方法导致 Activity 进入“已恢复”状态期间创建的组件。系统还会追踪布局中每个 View 对象的当前状态,如果用户在 EditText 组件中输入文本,系统将保留文本内容,因此我们无需保存和恢复文本。

注意:Activity 停止后,如果系统需要恢复内存,可能会销毁包含该 Activity 的进程。即使系统在 Activity
停止后销毁相应进程,系统仍会保留 Bundle(键值对的 blob)中 View 对象(例如
EditText组件中的文本)的状态,并在用户返回 Activity 时恢复这些对象。

进入“已停止”状态后,Activity 要么返回与用户互动,要么结束运行并销毁。如果 Activity 返回,系统将调用 onRestart()。如果 Activity 结束运行,系统将调用 onDestroy()。

onDestroy()

销毁 Ativity 之前,系统会先调用 onDestroy()。系统调用此回调的原因如下:

Activity 即将结束(由于用户彻底关闭 Activity 或由于系统为 Activity 调用 finish()),或者由于配置变更(例如设备旋转或多窗口模式),系统暂时销毁 Activity

我们应使用 ViewModel 对象来保存 Activity 的相关视图数据,而不是在 Activity 中加逻辑来确定 Activity 被销毁的原因。如果因配置变更而重新创建 Activity,ViewModel 不必执行任何操作,因为系统将保留 ViewModel 并将其提供给下一个 Activity 实例。如果不重新创建 Activity,ViewModel 将调用 onCleared() 方法,以便在 Activity 被销毁前清除所需的任何数据。

我们可以使用 isFinishing() 方法区分这两种情况。

如果 Activity 即将结束,onDestroy() 是 Activity 收到的最后一个生命周期回调。如果由于配置变更而调用 *onDestroy(),*系统会立即新建 Activity 实例,然后在新配置中为新实例调用 onCreate()。

onDestroy() 回调应释放先前的回调尚未释放的所有资源(例如 onStop())。

这篇关于【磨叽教程】Android进阶教程之Activity生命周期详解的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/817041

相关文章

Windows环境下解决Matplotlib中文字体显示问题的详细教程

《Windows环境下解决Matplotlib中文字体显示问题的详细教程》本文详细介绍了在Windows下解决Matplotlib中文显示问题的方法,包括安装字体、更新缓存、配置文件设置及编码調整,并... 目录引言问题分析解决方案详解1. 检查系统已安装字体2. 手动添加中文字体(以SimHei为例)步骤

Spring Boot中的路径变量示例详解

《SpringBoot中的路径变量示例详解》SpringBoot中PathVariable通过@PathVariable注解实现URL参数与方法参数绑定,支持多参数接收、类型转换、可选参数、默认值及... 目录一. 基本用法与参数映射1.路径定义2.参数绑定&nhttp://www.chinasem.cnbs

MySql基本查询之表的增删查改+聚合函数案例详解

《MySql基本查询之表的增删查改+聚合函数案例详解》本文详解SQL的CURD操作INSERT用于数据插入(单行/多行及冲突处理),SELECT实现数据检索(列选择、条件过滤、排序分页),UPDATE... 目录一、Create1.1 单行数据 + 全列插入1.2 多行数据 + 指定列插入1.3 插入否则更

Redis中Stream详解及应用小结

《Redis中Stream详解及应用小结》RedisStreams是Redis5.0引入的新功能,提供了一种类似于传统消息队列的机制,但具有更高的灵活性和可扩展性,本文给大家介绍Redis中Strea... 目录1. Redis Stream 概述2. Redis Stream 的基本操作2.1. XADD

Spring StateMachine实现状态机使用示例详解

《SpringStateMachine实现状态机使用示例详解》本文介绍SpringStateMachine实现状态机的步骤,包括依赖导入、枚举定义、状态转移规则配置、上下文管理及服务调用示例,重点解... 目录什么是状态机使用示例什么是状态机状态机是计算机科学中的​​核心建模工具​​,用于描述对象在其生命

Java JDK1.8 安装和环境配置教程详解

《JavaJDK1.8安装和环境配置教程详解》文章简要介绍了JDK1.8的安装流程,包括官网下载对应系统版本、安装时选择非系统盘路径、配置JAVA_HOME、CLASSPATH和Path环境变量,... 目录1.下载JDK2.安装JDK3.配置环境变量4.检验JDK官网下载地址:Java Downloads

使用Python删除Excel中的行列和单元格示例详解

《使用Python删除Excel中的行列和单元格示例详解》在处理Excel数据时,删除不需要的行、列或单元格是一项常见且必要的操作,本文将使用Python脚本实现对Excel表格的高效自动化处理,感兴... 目录开发环境准备使用 python 删除 Excphpel 表格中的行删除特定行删除空白行删除含指定

MySQL中的LENGTH()函数用法详解与实例分析

《MySQL中的LENGTH()函数用法详解与实例分析》MySQLLENGTH()函数用于计算字符串的字节长度,区别于CHAR_LENGTH()的字符长度,适用于多字节字符集(如UTF-8)的数据验证... 目录1. LENGTH()函数的基本语法2. LENGTH()函数的返回值2.1 示例1:计算字符串

Spring Boot spring-boot-maven-plugin 参数配置详解(最新推荐)

《SpringBootspring-boot-maven-plugin参数配置详解(最新推荐)》文章介绍了SpringBootMaven插件的5个核心目标(repackage、run、start... 目录一 spring-boot-maven-plugin 插件的5个Goals二 应用场景1 重新打包应用

mybatis执行insert返回id实现详解

《mybatis执行insert返回id实现详解》MyBatis插入操作默认返回受影响行数,需通过useGeneratedKeys+keyProperty或selectKey获取主键ID,确保主键为自... 目录 两种方式获取自增 ID:1. ​​useGeneratedKeys+keyProperty(推