Android四大组件之一,用于展示界面并和用户交互,每个activity都会获取一个绘制其用户界面的窗口(Window),窗口可以充满整个屏幕也可以小于屏幕并浮动在其他窗口之上。可以设置成一个dialog。

可以理解为语文中的上下文,也就是语境

从Android系统的角度来理解,Context就是当前应用所处的环境,

从程序的角度上来理解,Context是一个抽象类,Activity、Service、Application都是Context的子类

Activity发生ANR的时间是5秒

1、生命周期

Android如何删除多余版本的activityx依赖_android销毁时存储数据

基本方法介绍:

方法

介绍

onCreate

Activity创建,完成初始化操作

onRestart

当活动有停止状态变为运行状态时调用

onstart

Activity可见,但是不能进行交互

onResume

Activity有焦点,已经在前台活动

onPause

Activity失去焦点,退出前台活动,可以做存储数据、停止动画等操作

onStop

Activity不可见,可以做轻微重量级操作,如取消网络连接、注销广播接收器等

onDestrory

Activity被销毁,做回收工作、资源释放

onNewIntent

已存在实例,回到栈顶位置,SingleTask、SingleTop、SingleInstance模式下都可能会调用,生命周期在onPause回到onPause之前、onStop回到onStart之间

可以看出Activity的完整生命周期是onCreate -> onStart -> onResume -> onPause -> onStop,onDestroy

2、Activity的四个状态

运行状态

当一个Activity位于返回栈的栈顶时,最不会被系统回收的状态

暂停状态

当一个Activity不再处理栈顶位置,但仍然可见,当Activity被另一个透明或者Dialog样式的Activity覆盖时都会导致前一个Activity处于Pause状态,系统不会轻易回收的状态,除非是(内存极低的情况回收可见活动造成极不好的用户体验)

停止状态

不在栈顶位置,且不可见。当内存低的时系统会回收

销毁状态

不在栈中,系统会自动回收

优先级顺序:运行状态>暂停状态>停止状态>销毁状态

3、启动模式

1 Standard模式

安卓默认启动模式,这种模式下Activity可以有多个实例,无论任务栈是否已经有这个实例,系统都会创建一个新的Activity实例

启动A Acivity:onCreate-A -> onStart-A -> onResume-A

从A 跳转B:onPause-A -> onCreate-B -> onStart-B -> onResume-B -> onStop-A

从B回退到A:onPause-B -> onRestart-A -> onStart-A -> onResume-A -> onStop-B -> onDestroy-B (A启动A过程相同)

home或者锁屏:onPause-A -> onStop-A

home回到APP:onRestart-A -> onStart-A -> onResunme-A

直接kill掉进程:没有任何回调

2 SingleTask模式(栈内复用模式)

同一个Task内只有一个实例,如果Activity已经位于栈顶,系统不会创建新的Activity实例,和singleTop模式一样。但Activity已经存在但不位于栈顶时,就会将该Activity移到栈顶,并将它上面的Activity出栈

使用场景:浏览器、程序入口点

在栈顶的情况:

A启动A:onPause -> onNewIntent -> onResume

不在栈顶的情况:

A->B,从B启动A:onPause-B -> onNewIntent-A -> onRestart-A -> onStart-A -> onResume-A -> onStop-B -> onDestroy-B

A->B->C,从C启动A:onDestroy-B -> onPause-C -> onNewIntent-A -> onRestart-A -> onStart-A -> onResume-A -> onStop-C- > onDestroy-C

3 SingleTop模式(栈顶复用模式)

SingleTop模式与Standard模式很相似,主要区别是如果在栈顶,再去启动它时,不会创建新的实例,如果不位于栈顶,就会创建新实例

使用场景:搜索结果页

在栈顶的情况下:

A启动A:onPause -> onNewIntent -> onResume

不在栈顶的情况:

A->B,从B启动A:onPause-B -> onCreate-A -> onStart-A -> onResume-A -> onStop-B

A->B->C,从C启动A:onPause-C -> onCreate-A -> onStart-A -> onResume-A -> onStop-C

4 SingleInstance模式(单例模式)

singleInstance模式也是单例的,但和singleTask不同,singleTask只是任务栈内单例,系统里是可以有多个singleTask Activity实例的,而singleInstance Activity在整个系统里只有一个实例,启动一singleInstanceActivity时,系统会创建一个新的任务栈,并且这个任务栈只有他一个Activity。

生命周期和SingleTop大体一样

SingleInstance模式并不常用,启动时会慢一些,切换效果不好,影响用户体验。

使用场景:闹铃的响铃页面

闹钟界面,你以前设置了一个闹铃:上午6点。在上午5点58分,你启动了闹铃设置界面,并按Home键回桌面;在上午5点59分时,你在微信和朋友聊天;在6点时,闹铃响了,并且弹出了一个对话框形式的Activity(名为AlarmAlertActivity)提示你到6点了(这个Activity就是以SingleInstance加载模式打开的),你按返回键,回到的是微信的聊天界面,这是因为AlarmAlertActivity所在的Task的栈只有他一个元素,因此退出之后这个Task的栈空了。如果是以SingleTask打开AlarmAlertActivity,那么当闹铃响了的时候,按返回键应该进入闹铃设置界面。

4、启动方式

Activity之间通过Intent进行通信。Intent即意图,用于描述一个页面的信息,同时也是一个数据的载体。

启动方式分两种

显性启动

显性启动必须指定组件名

Intent intent = new Intent(ActivityMethods.this, OtherActivity.class)
startActivity(intent);

复制代码

隐性启动

隐性启动不指定组件名,而是通过在清单文件中activity节点下配置一个intent-filter,可以让自己的应用或其他应用通过匹配意图过滤器来打开当前的activity

Intent intent = new Intent("string_action");
//或者分开设置Action也可以
// intent.setAction("string_action");
startActivity(intent);

复制代码

想知道intent更多知识点见intent详解

启动带返回值的Activity

从A页面使用startActivityForResult()跳转到B页面,B页面点击返回时将新写入的值传回到A页面。

A使用startActivityForResult启动B,A重写onActivityResult()拿到从B返回来的数据

Intent intent = new Intent(AActivity.this, BActivity.class);
startActivityForResult(intent, 1);
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
switch (requestCode){
case 1 :
if(resultCode == RESULT_OK){
String returnData = data.getStringExtra("data_return");
Log.d("AActivity",returnData);
}
break;
default:
}
}

复制代码

B返回结果并finish
Intent intent = new Intent();
intent.putExtra("data_return","测试一下");//要返回的结果
setResult(RESULT_OK,intent);
finish();//销毁活动B

复制代码

5、onSaveInstanceState和onRestoreInstanceState

如果系统由于系统约束(而不是正常的应用程序行为)而破坏了Activity,那么尽管实际Activity实例已经消失,但是系统还是会记住它已经存在,这样如果用户导航回到它,系统会创建一个新的实例的Activity使用一组保存的数据来描述Activity在被销毁时的状态。系统用于恢复以前状态的已保存数据称为“实例状态”,是存储在Bundle对象中的键值对的集合。

Activity被异常销毁的时候会调用onSavaInstanceState方法,重建时会调用onRestoreInstanceState来获取已保存的数据,也可以通过onCreate 获取

发生场景

资源相关的系统配置发生改变(屏幕旋转)、内部不足、开启不保留活动等等。(用户主动按下返回键或者调用finish退出不会触发 )

方法回调时机

onSaveInstanceState在onStop之前回调

onRestoreInstanceState在onStart之后回调

也就是他们的回调是在Activity的暂停状态

异常退出数据保存 onSaveInstanceState

onSaveInstanceState保存Activity的附加状态信息,实现onSaveInstanceState()并向对象添加键值对Bundle。
static final String STATE_SCORE = "playerScore";
static final String STATE_LEVEL = "playerLevel";
...
@Override
public void onSaveInstanceState(Bundle savedInstanceState) {
// 保存用户自定义的状态
savedInstanceState.putInt(STATE_SCORE, mCurrentScore);
savedInstanceState.putInt(STATE_LEVEL, mCurrentLevel);
// 调用父类交给系统处理,这样系统能保存视图层次结构状态
super.onSaveInstanceState(savedInstanceState);
}

复制代码

异常退出数据恢复 onRestoreInstanceState

当Activity在之前被破坏后重新创建时,可以从Bundle系统通过Activity中恢复保存状态。这两个方法onCreate()和onRestoreInstanceState()回调方法都会收到Bundle包含实例状态信息的相同方法。

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); // 记得总是调用父类
// 检查是否正在重新创建一个以前销毁的实例
if (savedInstanceState != null) {
// 从已保存状态恢复成员的值
mCurrentScore = savedInstanceState.getInt(STATE_SCORE);
mCurrentLevel = savedInstanceState.getInt(STATE_LEVEL);
} else {
// 可能初始化一个新实例的默认值的成员
}
...
}

复制代码

或者

public void onRestoreInstanceState(Bundle savedInstanceState) {
// 总是调用超类,以便它可以恢复视图层次超级
super.onRestoreInstanceState(savedInstanceState);
// 从已保存的实例中恢复状态成员
mCurrentScore = savedInstanceState.getInt(STATE_SCORE);
mCurrentLevel = savedInstanceState.getInt(STATE_LEVEL);
}

复制代码

系统onRestoreInstanceState()只有在存在保存状态的情况下才会恢复,因此不需要检查是否Bundle为空:

例子:

开启不保留活动,跳到另一个Activity时:

onPause -> onSaveInstanceState -> onStop -> onDestroy

回到上一个Activity时:

onCreate -> onStart -> onRestoreInstanceState -> onResume

扩展