侧边栏壁纸
博主头像
爱探索

行动起来,活在当下

  • 累计撰写 42 篇文章
  • 累计创建 11 个标签
  • 累计收到 2 条评论

目 录CONTENT

文章目录

Android-activity详解

jelly
2024-07-05 / 0 评论 / 0 点赞 / 30 阅读 / 0 字

activity详解

生命周期分析

onCreate(savedInstanceState: Bundle?)

Activity被启动时的第一个方法,表示Activity正在被创建,在这个方法中一般做一些初始化的工作,比如调用setContentView方法加载界面布局,并且可以做一些初始化数据的工作:声明UI元素,定义成员变量,配置UI等。
这个时候应用在创建过程中hai

onStart()

acitivity被创建完成进入启动状态,在该状态中视图已经准备完成,但是这是还不能被用户所看见

onResume()

此时Activity来到前台和用户进行交互,用户真正的看到了Activity.

onPasue()

表示Activity正在停止,该状态下,activity的部分被另外一个activity所遮盖:另外的activity来到前台,但是半透明的,不会覆盖整个屏幕。被暂停的activity不再接受用户的输入且不再执行任何代码。

onStop

该状态下, activity完全被隐藏,对用户不可见。可以认为是在后台。当stopped, activity实例与它的所有状态信息(如成员变量等)都会被保留,但activity不能执行任何代码。

onRestatus

当activity从onStop中恢复时调用,Activity从不可见又变为可见时会调用。此时调用顺序为:onRestart -> onStart -> onResume

onDestroy()

表示Activity即将被销毁,当收到需要将该activity彻底移除的信号时,系统会调用这个方法。

activity异常情况下生命周期分析

1. 系统配置发生改变导致activity被杀死重建(屏幕发生旋转)

当acitvity发生旋转后,该activity会被销毁 会调用其onPause,onStop,onDestroy方法均会被调用 同时由于时异常终止所以还要调用 onSaveInstanceState(outState: Bundle)方法保存一些参数,该方法是在onStop()之后。在现销毁之后activity会重现(一个新对象) onCreate(savedInstanceState: Bundle?) onStart onResume()都会调用并且会调用onRestoreInstanceState(savedInstanceState: Bundle) 获取到在销毁是所保存的参数,该函数的调用时机是在onStart()之后
当因为屏幕旋转或内存压力等原因造成activity销毁,虽然实际的 Activity 实例会消失,但系统会记住它曾经存在过。如果用户尝试回退到该 Activity,系统将使用一组描述 Activity 销毁时状态的已保存数据新建该 Activity 的实例。

2. 应用程序前后台切换

当activity进入后台是在调用onPause(),onStop()后太会调用onSaveInstanceState(outState: Bundle) ,但是在程序再次进入前台时调用onRestart() onStart() onResume()但是缺不会再调用onRestoreInstanceState(savedInstanceState: Bundle)

3. 手动再任务管理中杀死程序

进入任务管理界面时程序会进入后台状态会执行onPause(),onStop()(这里将不在赘述onSaveInstanceState函数)当杀死程序时onDestroy()函数并不能保证一定会执行

4. activity 之间跳转

当activityA跳转到activityB时生命周期发生一下变化(A的生命周期前面夹A标识B的加B标识,例如A的onCreate为 AonCreate):

A的生命周期调用为AonPause()后,Bactivity启动调用BonCreate(),BonStart(),BonResume(),这是B显示后A调用AonStop

activity数据保存与恢复onSaveInstanceState,onRestoreInstanceState

1. onSaveInstanceState(outState: Bundle?)

再activity开始停止时系统会调用onSaveInstanceState(outState: Bundle?) 函数保存一些轻量级数据,例如控件状态,textView中的数据,如果需要保存其他实例状态,则需要重写onSaveInstanceState函数将这些实例写入Bundle中以便再activity恢复时获取。

当activity需要保存一些持久化数据这时使用onSaveInstanceState是不适用的,需要使用数据库、sp或viewmode等方式去保存

2. onRestoreInstanceState(savedInstanceState: Bundle?)||onCreate(savedInstanceState: Bundle?)

再恢复数据时可以再两个函数中恢复onCreate,与onRestoreInstanceState。但是onCreate再正常启动或者异常重建都会调用所以需要检查一下Bundle是否为null,如果正常启动则不会有恢复的数据这是Bundle会为null,异常销毁重建如果有保存的数据则不会为null

onRestoreInstanceState该函数只会再有保存的数据时才会调用所以不存在null问题,但是该函数调用时机时onStart。如果一些数据需要再onCreate时恢复则不适用

activity 启动模式

activity 有以下四种启动模式:standard、singleTop、singleTask、singleInstance

1. standard

Activity的默认启动模式,每次启动已个activity都会创建一个实例并且压入同一个任务栈中

例如:

当一个任务栈中有A、B、C、D,activity它们的顺序是(A->B->C->D D位于栈顶)如果再这个时候收到以 D 类型 Activity 为目标的 intent则会创建一个新的D类型的Activity并压入栈中,这是栈中顺序为(A->B->C->D->D D位于栈顶)

2. singleTop

如果收到的启动Activity intent中Activity类型与任务栈中栈顶Activity类型相同则不会再创建新的Activity实例,如果栈顶元素与收到的activity类型不同则创建新的实例并压入栈中

例如:

当一个任务栈中有A、B、C、D,activity它们的顺序是(A->B->C->D D位于栈顶)如果再这个时候收到以 D 类型 Activity 为目标的intent,这时因为栈顶activityD与需要被启动的activityD相同所以栈顶activity会在onNewIntent(intent: Intent?)函数中接收到该Intent ,这是栈中顺序为(A->B->C->D D位于栈顶)

1.1 singleTop对activity生命周期的影响

如果启动的activity与栈顶activity类型不一样则生命周期没有什么特殊变化这里不在讨论。当启动的activity与栈顶activity类型不一样时生命周期会有所变化,例如:栈顶元素为actvityD(后面称为taskTop)这是在启动一个activityD(),栈顶元素activityD生命周期为:onPasue->onNewIntent-> onResume 。 这里onPasue之后不会再调用onStop onDestroy。onResume之前调用的是onNewIntent,不会调用onCreate,onStart

注创建 Activity 的新实例后,用户可以按返回按钮返回到上一个 Activity。但是,当由 Activity 的现有实例处理新 intent 时,用户将无法通过按返回按钮返回到 onNewIntent() 收到新 intent 之前的 Activity 状态。

3. singleTask

栈内单例实例,如果启动一个activity为singleTask模式哪个那会先检查任务栈中有没有相同的activity 如果不存在则创建实例并压栈,如果栈中存在,则将该实例恢复至栈顶,然后将intent转值该实例的onNewIntent中,再出栈过程中会将实例之上的所有activity实例出栈并finish()

4 singleInstance

每次以singleInstance模式启动activity系统都会创建一个新的任务栈并将activity实例压栈,该activity独享该任务栈,启动启动时如果有一个任务栈存在和启动的activity一样类型的activity则不会再创建新的实例,而是将intent转到该实例的onNewIntent中

4.1 singleInstance对生命周期的影响

如果启动的activity与栈顶activity类型不一样则生命周期没有什么特殊变化。如果一样则有两个情况:1.其他任务栈有一样的实例2.当前任务栈存在相同的实例

  1. 当前任务栈存在相同类型实例

当前任务栈存在相同类型实例已有一种方式,即actvityA(后面称为A1)启动activityA(后面称为A2),这时A1生命周期为 onPasue->onNewIntent-> onResume,A2不会创建新实例

  1. 其他任务栈存在相同的实例

生命周期为onstart-> onNewIntent-> onResume。因为这个实例不在前台所以不会调用onPasue,但是会调用onStart(因为它从后台切换到了前台)

4.2 singleInstance对回退栈的影响

假设想在有三个activity分别是A(standard,Main)B(singleInstance) C(standard),现在执行一下操作:

  1. 启动APP 进入A界面
  2. 从A中启动B界面
  3. 从B中启动C

执行完以上操作之后这是执行返回操作它的返回栈还能是C->B->A吗?。答案是:不能这样返回,因为C,A属于一个任务栈,B属于一个任务栈,如果这是返回,C出栈返回后这是栈顶元素是A,多以这时显示的时A界面,A返回后才是B界面,B返回则App退出。它的返回顺序时C->A->B

在多种启动模式混合使用时他的任务栈将变得复杂,并且返回栈可能发生一些变化,这要特别注意。

使用 Intent 标记启动模式

1. FLAG_ACTIVITY_SINGLE_TOP

行为与singleTop一样

1. FLAG_ACTIVITY_NEW_TASK

行为与singleTask一样

3. FLAG_ACTIVITY_CLEAR_TOP

如果要启动的 Activity 已经在当前任务中运行,则不会启动该 Activity 的新实例,而是会销毁位于它之上的所有其他 Activity,并通过 onNewIntent() 将此 intent 传送给它的已恢复实例(现在位于堆栈顶部)注:必须是相同任务栈

如果FLAG_ACTIVITY_CLEAR_TOP与FLAG_ACTIVITY_NEW_TASK一起使用则会在会在所有任务栈中查早activity,并将其置于能够响应 intent 的位置

注意:如果指定 Activity 的启动模式为 "standard",系统也会将其从堆栈中移除,并在它的位置启动一个新实例来处理传入的 intent。这是因为当启动模式为 "standard" 时,始终会为新 intent 创建新的实例。

清除返回堆栈

如果用户离开任务较长时间,系统会清除部分activity,当用户再次进入后会恢复部分activity,系统之所以采取这种行为方式是因为,经过一段时间后,用户可能已经放弃了之前执行的操作,现在返回任务是为了开始某项新的操作。

具体的行为可以用过一下属性控制

  • alwaysRetainTaskState
  • clearTaskOnLaunch
  • finishOnTaskLaunch

1. alwaysRetainTaskState

如果在xml中配置alwaysRetainTaskState为true,则在用户离开一段时间后任务会保留所以activity不会进行清除行为

2. clearTaskOnLaunch

如果在xml中配置clearTaskOnLaunch为true,则在用户离开一点时间后任务会清除除根activity以外的所有activity,当用户再次进入时,用户始终会返回到任务的初始状态,即便只是短暂离开任务也是如此。

3. finishOnTaskLaunch

但它只会作用于单个 Activity 而非整个任务。它还可导致任何 Activity 消失,包括根 Activity。如果将该属性设为 "true",则 Activity 仅在当前会话中归属于任务。如果用户离开任务再返回,则该任务将不再存在。

启动任务

我们可以通过给一个activity 指定intent 并只当"android.intent.action.MAIN" 作为指定操作,将 "android.intent.category.LAUNCHER" 作为指定类别, 来将activity设置为app的入口点

例如:


    <activity android:name=".MainActivity">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />

            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>

只有当一个activity 拥有android.intent.action.MAIN与android.intent.category.LAUNCHER 过滤器时才可以将其设置为才应使用 "singleTask" 和 "singleInstance" 这两种启动模式,这时这个activity会被 标记为始终启动任务。

activity 常用标签说明

android:exported

该标签的值为true时,该界面可以被外部的程序调用。当为false时该界面不能被外部程序调用,如果该部调用则报以下错误:


    Caused by: java.lang.SecurityException: Permission Denial: starting Intent 

注:在四大组件中功能相同

其他问题

activitys栈中关闭非栈顶activity对该activity只上的影响

activityA activityB activityC

操作:activityA跳转activityB跳转activityC,如果这时关闭activityA对activityB于activityC有没有影响

0

评论区