Android四大组件之一,用于展示界面并和用户交互,每个activity都会获取一个绘制其用户界面的窗口(Window),窗口可以充满整个屏幕也可以小于屏幕并浮动在其他窗口之上。可以设置成一个dialog。
可以理解为语文中的上下文,也就是语境
从Android系统的角度来理解,Context就是当前应用所处的环境,
从程序的角度上来理解,Context是一个抽象类,Activity、Service、Application都是Context的子类
Activity发生ANR的时间是5秒
1、生命周期
基本方法介绍:
方法
介绍
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
扩展