Activity的启动和结束
创始人
2024-05-31 05:44:15
0
  1. onCreate:创建活动。此时会把页面布局加载进内存,进入了初始状态。

  1. onStart:开启活动。此时会把活动页面显示在屏幕上,进入了就绪状态。

  1. onResume:恢复活动。此时活动页面进入活跃状态,能够与用户正常交互,例如允许响应用户的点击动作、允许用户输入文字等。

  1. onPause:暂停活动。此时活动页面进入暂停状态(也就是退回就绪状态),无法与用户正常交

  1. 互。

  1. onStop:停止活动。此时活动页面将不在屏幕上显示。

  1. onDestroy:销毁活动。此时回收活动占用的系统资源,把页面从内存中清除掉。

  1. onRestart:重启活动。处于停止状态的活动,若想重新开启的话,无须经历onCreate的重复创建过程,而是走onRestart的重启过程。

  1. onNewIntent:重用已有的活动实例。

上述的生命周期方法,涉及复杂的App运行状态,更直观的活动状态切换过程如图4-2所示。

主页

跳转

返回

如果一个Activity已经启动过,并且存在当前应用的Activity任务栈中,启动模式为singleTask,singleInstance或singleTop(此时已在任务栈顶端),那么在此启动或回到这个Activity的时候,不会创建新的实例,也就是不会执行onCreate方法,而是执行onNewIntent方法。

Activity的启动模式

第一个活动跳到第二个活动,接着结束第二个活动就能返回第一个活动,可是为什么不直接返回桌面呢?

这要从Android的内核设计说起了,系统给每个正在运行的App都分配了活动栈,栈里面容纳着已经创建且尚未销毁的活动信息。

鉴于栈是一种先进后出、后进先出的数据结构,故而后面入栈的活动总是先出栈,

假设3个活动的入栈顺序为:活动A→活动B→活动C,则它们的出栈顺序将变为:活动C→活动B→活动A,

可见活动C结束之后会返回活动B,而不是返回活动A或者别的地方。假定某个App分配到的活动栈大小为3,该App先后打开两个活动,此时活动栈的变动情况如图

实际上Android允许在创建活动时指定该活动的启动模式,通过启动模式控制活动的出入栈行为。App提供了两种办法用于设置活动页面的启动模式,其一是修改AndroidManifest.xml,在指定的activity节点添加属性android:launchMode,表示本活动以哪个启动模式运行。其二是在代码中调用Intent对象的setFlags方法,表明后续打开的活动页面采用该启动标志。下面分别予以详细说明。

在两个活动之间交替跳转

假设活动A有个按钮,点击该按钮会跳到活动B;同时活动B也有个按钮,点击按钮会跳到活动A;从首页打开活动A之后,就点击按钮在活动A与活动B之间轮流跳转。此时活动页面的跳转流程为:首页→活动A→活动B→活动A→活动B→活动A→活动B→……多次跳转之后想回到首页,正常的话返回流程是这样的:……→活动B→活动A→活动B→活动A→活动B→活动A→首页,注意每个箭头都代表按一次返回键,

对于不允许重复返回的情况,可以设置启动标志FLAG_ACTIVITY_CLEAR_TOP,即使活动栈里面存在待跳转的活动实例,也会重新创建该活动的实例,并清除原实例上方的所有实例,保证栈中最多只有该活动的唯一实例,从而避免了无谓的重复返回。于是活动A内部的跳转代码就改成了下面这般:

package com.example.myapplication_03;import android.content.Intent;
import android.os.Bundle;
import android.view.View;import androidx.appcompat.app.AppCompatActivity;public class JumpFirstActivity extends AppCompatActivity implements View.OnClickListener {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_jump_first);findViewById(R.id.btn_jump_second).setOnClickListener(this);}@Overridepublic void onClick(View v) {// 创建一个意图对象,准备跳到指定的活动页面Intent intent = new Intent(this, JumpSecondActivity.class);// 栈中存在待跳转的活动实例时,则重新创建该活动的实例,并清除原实例上方的所有实例intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);startActivity(intent);}
}

当然活动B内部的跳转代码也要设置同样的启动标志:

package com.example.myapplication_03;import android.content.Intent;
import android.os.Bundle;
import android.view.View;import androidx.appcompat.app.AppCompatActivity;public class JumpSecondActivity extends AppCompatActivity implements View.OnClickListener {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_jump_second);findViewById(R.id.btn_jump_first).setOnClickListener(this);}@Overridepublic void onClick(View v) {// 创建一个意图对象,准备跳到指定的活动页面Intent intent = new Intent(this, JumpFirstActivity.class);// 栈中存在待跳转的活动实例时,则重新创建该活动的实例,并清除原实例上方的所有实例intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);startActivity(intent);}
}

这下两个活动的跳转代码都设置了FLAG_ACTIVITY_CLEAR_TOP,运行测试App发现多次跳转之后,每个活动仅会返回一次而已。

登录成功后不再返回登录页面

很多App第一次打开都要求用户登录,登录成功再进入App首页,如果这时按下返回键,发现并没有回到上一个登录页面,而是直接退出App了

对于回不去的登录页面情况,可以设置启动标志FLAG_ACTIVITY_CLEAR_TASK,该标志会清空当前活动栈里的所有实例。不过全部清空之后,意味着当前栈没法用了,必须另外找个活动栈才行,也就是同时设置启动标志FLAG_ACTIVITY_NEW_TASK,该标志用于开辟新任务的活动栈。于是离开登录页面的跳转代码变成下面这样:

package com.example.myapplication_03;import android.content.Intent;
import android.os.Bundle;
import android.view.View;import androidx.appcompat.app.AppCompatActivity;public class LoginInputActivity extends AppCompatActivity implements View.OnClickListener {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_login_input);findViewById(R.id.btn_jump_success).setOnClickListener(this);}@Overridepublic void onClick(View v) {// 创建一个意图对象,准备跳到指定的活动页面Intent intent = new Intent(this, LoginSuccessActivity.class);// 设置启动标志:跳转到新页面时,栈中的原有实例都被清空,同时开辟新任务的活动栈intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK);startActivity(intent);}
}

默认启动模式 standard

该模式可以被设定,不在 manifest 设定时候,Activity 的默认模式就是 standard。在该模式下,启动的 Activity 会依照启动顺序被依次压入 Task 栈中:

栈顶复用模式 singleTop

在该模式下,如果栈顶 Activity 为我们要新建的 Activity(目标Activity),那么就不会重复创建新的Activity。

适合开启渠道多、多应用开启调用的 Activity,通过这种设置可以避免已经创建过的 Activity 被重复创建,多数通过动态设置使用。

栈内复用模式 singleTask

与 singleTop 模式相似,只不过 singleTop 模式是只是针对栈顶的元素,而 singleTask 模式下,如果task 栈内存在目标 Activity 实例,则将 task 内的对应 Activity 实例之上的所有 Activity 弹出栈,并将对应 Activity 置于栈顶,获得焦点

程序主界面:我们肯定不希望主界面被创建多次,而且在主界面退出的时候退出整个 App 是最好的效果。

耗费系统资源的Activity:对于那些及其耗费系统资源的 Activity,我们可以考虑将其设为 singleTask模式,减少资源耗费。

全局唯一模式 singleInstance

在该模式下,我们会为目标 Activity 创建一个新的 Task 栈,将目标 Activity 放入新的 Task,并让目标Activity获得焦点。新的 Task 有且只有这一个 Activity 实例

如果已经创建过目标 Activity 实例,则不会创建新的 Task,而是将以前创建过的 Activity 唤醒。

看一个示例,Activity3 设置为singleInstance,Activity1 和 Activity2 默认(standard),下图程序流程中,黄色的代表 Background 的Task,蓝色的代表 Foreground 的Task。返回时会先把 Foreground 的Task 中的 Activity 弹出,直到 Task 销毁,然后才将 Background的 Task 唤到前台,所以最后将Activity3 销毁之后,会直接退出应用。
(3是单独的任务栈)

动态设置启动模式

在上述所有情况,都是我们在Manifest中通过 launchMode 属性设置的,这个被称为静态设置,动态设置是通过 Java 代码设置的。通过 Intent 动态设置 Activity启动模式

intent.setFlags();

如果同时有动态和静态设置,那么动态的优先级更高。

FLAG_ACTIVITY_NEW_TASK

Intent.FLAG_ACTIVITY_NEW_TASK

此 Flag 跟 singleInstance 很相似,在给目标 Activity 设立此 Flag 后,会根据目标 Activity 的 affinity 进行匹配,如果已经存在与其affinity 相同的 task,则将目标 Activity 压入此 Task。反之没有的话,则新建一个 task,新建的 task 的 affinity 值与目标 Activity 相同,然后将目标 Activity 压入此栈。但它与 singleInstance 有不同的点,两点需要注意的地方:

新的 Task 没有说只能存放一个目标 Activity,只是说决定是否新建一个 Task,而 singleInstance模式下新的 Task 只能放置一个目标 Activity。在同一应用下,如果 Activity 都是默认的 affinity,那么此 Flag 无效,而 singleInstance 默认情况也会创建新的 Task。

FLAG_ACTIVITY_SINGLE_TOP

Intent.FLAG_ACTIVITY_SINGLE_TOP

此 Flag 与静态设置中的 singleTop 效果相同

FLAG_ACTIVITY_CLEAR_TOP

Intent.FLAG_ACTIVITY_CLEAR_TOP

当设置此 Flag 时,目标 Activity 会检查 Task 中是否存在此实例,如果没有则添加压入栈。如果有,就将位于 Task 中的对应 Activity 其上的所有 Activity 弹出栈,此时有以下两种情况:

如果同时设置 Flag_ACTIVITY_SINGLE_TOP ,则直接使用栈内的对应 Activity。

intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP |Intent.FLAG_ACTIVITY_SINGLE_TOP);

没有设置,则将栈内的对应 Activity 销毁重新创建。

按位或运算符运算规则:0|0=0 0|1=1 1|0=1 1|1=1

总结:参加运算的两个对象只要有一个为1,其值为1。

例如:3|5即 0000 0011| 0000 0101 = 0000 0111,因此,3|5的值得7

相关内容

热门资讯

九年级我该怎么过700字作文... 九年级我该怎么过700字作文 篇一九年级对于我来说是一个非常重要的阶段,它标志着我即将迈入高中的大门...
知恩初三作文【精彩3篇】 知恩初三作文 篇一:感恩父母作为一个初三学生,我深刻地意识到自己应该对父母心怀感恩之情。他们是我成长...
初三漂流作文800字(优质6... 初三漂流作文800字 篇一初三漂流这个寒假,我和几个好朋友决定去体验一次漂流的刺激。我们选择了一个位...
初三家教手册:给儿子成长的机... 初三家教手册:给儿子成长的机会 篇一家庭教育是孩子成长过程中至关重要的一环。特别是对于初三的孩子来说...
九年级你好作文700字【最新... 九年级你好作文700字 篇一初中生活的收获与感悟初中生活即将结束,回首这三年的时光,我仿佛看到了一幅...
初三100多字的优美句子【精... 初三100多字的优美句子 篇一初三,是我们人生中一个重要的阶段。这个阶段的我们正在开始追寻自己的梦想...
向目的地进发初三作文800字... 向目的地进发初三作文800字 篇一目的地,是每个人心中的追求和向往。初三,是每个中学生成长的关键时期...
美味寿司初三作文(最新3篇) 美味寿司初三作文 篇一:探寻寿司的魅力寿司,是一道源自日本的美食,以其精致的制作工艺和独特的口感,在...
师恩难忘初三优秀作文600字... 师恩难忘初三优秀作文600字 篇一师恩难忘初三,是我人生中最难忘的一年。这一年里,我经历了许多事情,...
半瓢初三我沉浮 -初中作文(... 半瓢初三我沉浮 -初中作文 篇一初三,是一个让人充满期待和焦虑的阶段。对于我来说,初三的生活就像是在...
感谢你我的老师初三作文(经典... 感谢你我的老师初三作文 篇一在我初三的这一年里,我结识了许许多多的老师,他们用他们的知识和智慧,引导...
初三毕业留言英文大全(精简3... 初三毕业留言英文大全 篇一Dear Classmates,As we reach the end o...
献给全天下为学生带来温暖的老... 献给全天下为学生带来温暖的老师们初三作文 篇一老师,您是我们成长道路上的指路明灯,是我们学习生活中的...
忘不了的那个人初三作文【精彩... 忘不了的那个人初三作文 篇一那个人,是我初三时候班上的一位同学,他的名字叫李明。李明是一个非常聪明而...
九年级作文我的新老师(优质6... 九年级作文我的新老师 篇一我的新老师我很庆幸在这个学期里遇到了一位特别好的新老师,她就是我们班的班主...
雨夜初三上册语文第一单元作文... 雨夜初三上册语文第一单元作文450字 篇一雨夜初三上册语文第一单元作文450字 篇一 雨夜初三上册语...
初三语文作文(优秀6篇) 初三语文作文 篇一:我的偶像作为一个初三学生,我有许多偶像。他们有的是优秀的运动员,有的是杰出的科学...
初三毕业赠言(通用3篇) 初三毕业赠言 篇一初三毕业了,时间过得真快。回顾这三年的学习生活,我不禁感慨万分。在这里,我想给同学...
我的初三生活作文【精选6篇】 我的初三生活作文 篇一初三,对于每一个初中生来说都是一个重要的阶段。对我而言,初三不仅仅是一个学习的...
写初三的幸福作文500字(优... 写初三的幸福作文500字 篇一初三是学生生活中最为重要的一年,也是最为紧张和忙碌的一年。然而,尽管充...