前言:Activity是android四大组件之一,同时也是在开发时用到最多的组件,但要细分的话知识点也是挺多的,通过这篇文章进行总结。
一.Activity的四种状态
![](https://img.haomeiwen.com/i6600660/c8a0ff3829724906.png)
二.Activity的生命周期(正常情况下)
![](https://img.haomeiwen.com/i6600660/eba35c52846d5c4f.png)
生命周期 | 说明 |
---|---|
onCreate() |
Activity已经被创建完毕,当Activity第一次启动的时候,触发该方法,可以在此时完成Activity的初始化工作。 |
onStart() |
此方法在活动由不可见变为可见时调用,此时activity已经显示在屏幕上,但没有获得焦点 |
onResume() |
此方法在活动准备好和用户交互时地阿偶用,activity得到焦点。此时的活动已定位与返回栈的栈顶,并且处于运行状态 |
onPause() |
此方法在活动失去焦点,无法再与用户交互,但依然可见。当一个正在前台运行的Activity因为其他的Activity需要前台运行而转入后台运行的时候,触发该方法。 |
onStop() |
此方法在活动完全不可见时调用。但注意,所有保存信息的工作都不应该在此方法中进行,应该在onPause中进行 |
onDestroy() |
此方法在活动被销毁前调用。但是注意,内存紧张时,系统会直接杀死活动而不会调用onDestory或onStop方法 |
onResstart() |
当处于停止状态的Activity需要再次展现给用户的时候,触发该方法,即从不可见变成可见时会执行此方法 |
以上的7个方法除了onResstart方法外,其他都是两两相对的,从而又可以将活动分为3种生存期
- 完整生存期:onCreate→onDestory
- 可见生存期:onStart→onStop
- 前台生存期:onResume→onPause
正常生命周期中一些常见的问题
1.什么情况下会执行:onPause()->onResume()
1.在当前Activity上面有个Dialog,并且退出Dialog
2.Activity先执行onPause()
处于可见、不可交互,然后回到onResume()
进入可交互状态。
2.什么情况下会执行:onStop()->onRestart()->onResume()
1.从新的Activity返回到当前Activity时
2.切换到桌面,又切换回当前Activity。
3.什么情况下执行: onPause()->onCreate() 或者 onStop()->onCreate()
系统内存不足,导致Activity在对应周期被杀死。然后重建该Activity
4.onCreate()和onStart()的区别
1.执行1次/执行多次
2.onCreate()
能做的,onStart()
都能做, 除非只适合执行一次的逻辑
3.onCreate()
处于不可见,onStart()
可见但不可交互
5.什么情况下执行: onPause()->onCreate() 或者 onStop()->onCreate()
系统内存不足,导致Activity在对应周期被杀死。然后重建该Activity
6.onStart和onResume的区别
1.均可见,前者不可交互,后者可交互
2.官方建议onResume()
中可以做开启动画和独占设备的操作
7.onPause和onStop的区别
1.前者可见,后者不可见
2.内存不足时一定会执行onPause(),onStop()
不一定执行
3.保存数据最好在onPause()
中,但不能太耗时
4.尽量将重量级操作放在onStop()
中能够提高打开新Activity的速度(onPause()
会影响新Activity的创健)
8.onStop和onDestory的区别
1.
onStop()
时,Activity依旧在内存中,可以切换回该Activity。
2.onDestory()
时,已经被系统释放了
三.Activity的生命周期(异常情况下)
1.Activity异常生命周期
是指Activity被系统回收或者由于当前设备的Configuration(方向)发生改变从而导致Activity被销毁重建
生命周期 | 说明 |
---|---|
onSaveInstanceState(bundle outState) |
Activity被销毁时调用,保存重要信息,用于恢复 |
onRestoreInstanceState(bundle savedInstanceState) |
重建时调用,会将bundle传递到onCreate() 中 |
1.用户主动销毁Activity不会触发
onSaveInstanceState()
,如finish()、按下回退键退出Activity
2.按下HOME键、按下电源键、启动其他Activity、横竖屏切换: 如果导致了Activity的重建,会触发onSaveInstanceState()
2.什么情况下可能会导致Activity的重建?
1.按下HOME键
2.按下电源键
3.启动其他Activity
4.横竖屏切换
3.如果Activity被意外关闭,如何判断Activity是否被重建?
1.通过
onRestoreInstanceState()
和onCreate()
方法来判断。
2.onRestoreInstanceStae()
被调用,或者onCreate()
的参数Bundle不为null。都表明Activity被重建
3.因为Activity被异常关闭后,那么系统会调用onSaveInstanceState()
保存当前Activity的状态。
4.资源相关的系统配置改变导致Activity的杀死并重建
场景: Activity的横竖屏切换
1.系统配置改变后,Activity会被销毁,其
onPause()
、onStop()
、onDestory()
均会被调用
2.系统会额外调用onSaveInstanceState()
来保存当前Activity的状态, 调用时机在onPause()
前后(onStop()
之前)
3.Activity重新创建后,会调用onRestoreInstanceState()
并且把onSaveInstanceState()
保存的Bundle对象作为参数同时传递给onRestoreInstanceState()
和onCreate()
, 其调用时机在onStart()
之后
4.系统会默认保存当前Activity的视图结构并且恢复一定数据。根据每个View的onSaveInstanceState()
和onRestoreInstanceState()
可以知道系统能自动恢复哪些数据。
5.系统保存和恢复View层次结构的工作流程
1.Activity被意外终止时,会调用
onSaveInstanceState()
去保存数据
2.Activity去委托Window保存数据
3.Window再委托顶层容器去保存数据(ViewGroup:一般是DecorView)
4.顶层容器最后一一通知其子元素保存数据
横竖屏切换
1.如何在Activity禁止横竖屏切换?
1.在AndroidManifest中给相应的Activity添加上属性
android:screenOrientation="portrait"
2.portrait为竖屏
3.landscape为横屏
4.或者可以在onCreate中添加代码setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT/LANDSCAPE);
5.最终会禁止横竖屏切换,也不会触发保存数据/恢复数据的回调
2.如何实现Activity在横竖屏切换时,禁止Activity的重建?(通过configChanges实现)
1.给Activity添加属性:
android:configChanges="orientation|screenSize
"
2.Activity不会再销毁和重建,只会调用onConfigurationChanged()
方法,可以进行特殊处理。
3.禁止了Activity的横竖屏切换(重建)后, 什么回调方法会在横竖屏切换时被调用?
onConfigurationChanged()
4.通过禁止了横竖屏从而禁止了Activity的重建,既然Activity不再会重建,也就不需要再去处理数据的保存和恢复?
错误!
内存不足时,依旧可能会出现Activity被杀死并且重建的情况。
四.Activity的跳转和数据传输
显式 Intent
:按名称(完全限定类名)指定要启动的组件。 通常,您会在自己的应用中使用显式 Intent 来启动组件,这是因为您知道要启动的 Activity 或服务的类名。例如,启动新 Activity 以响应用户操作,或者启动服务以在后台下载文件。
隐式 Intent
:不会指定特定的组件,而是声明要执行的常规操作,从而允许其他应用中的组件来处理它。 例如,如需在地图上向用户显示位置,则可以使用隐式 Intent,请求另一具有此功能的应用在地图上显示指定的位置。
1.使用显示intent
Intent intent = new Intent(MainActivity.this,SecondActivity.class);
startActivity(intent);
![](https://img.haomeiwen.com/i6600660/3212949077063716.gif)
2.使用隐式intent
通过配置在<activity>标签下的<intent-filter>的内容,制定当前活动能够响应的action和category。
<activity android:name=".SecondActivity">
<intent-filter>
<action android:name="com.example.activitytest.ACTION_START"/>
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
</activity>
修改点击事件中的代码
Intent intent = new Intent("com.example.activitytest.ACTION_START");
//如果需要添加Category,需要在intent-filter标签中加上声明
//intent.addCategory("com.example.activitytest.MY_CATEGORY_1");
//intent.addCategory("com.example.activitytest.MY_CATEGORY_2");
startActivity(intent);
3.向下一个活动传递数据
修改mainactivity中的代码,存入传输数据
String data = "hello android";
Intent intent = new Intent(MainActivity.this,SecondActivity.class);
intent.putExtra("extra_data",data);
startActivity(intent);
在下一个活动提取数据
Intent intent = getIntent();
String data = intent.getStringExtra("extra_data");
Log.d("SecondActivity",data);
3.返回数据给上一个活动
使用startActivityForResult()
开启下一个活动,请求码唯一即可
Intent intent = new Intent(MainActivity.this,SecondActivity.class);
startActivityForResult(intent,1);
在下一个活动准备返回第一个活动的数据
Intent intent = new Intent();
intent.putExtra("data_return","hello android");
setResult(RESULT_OK,intent);
finish();
在第一个活动中重写onActivityResult()
方法获取数据
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
if(resultCode==RESULT_OK){
String returnData = data.getStringExtra("data_return");
Log.d("MainActivity",returnData);
}
}
四.Activity的四种启动模式
1.standard(默认)
不会复用任务栈中的Activity,而是新建Activity实例添加到栈顶。新Activity位于启动者的任务栈中
![](https://img.haomeiwen.com/i6600660/5ebc5d22957aafcf.png)
2.栈顶复用模式singleTop
在该模式下,如果栈顶Activity为我们要新建的Activity(目标Activity),那么就不会重复创建新的Activity。
![](https://img.haomeiwen.com/i6600660/c0b13ebacf589353.png)
使用场景
1.IM消息
2.新闻客户端推送
3.栈内复用模式singleTask
与singleTop模式相似,只不过singleTop模式是只是针对栈顶的元素,而singleTask模式下,如果task栈内存在目标Activity实例,则:
1.将task内的对应Activity实例之上的所有Activity弹出栈。
2.将对应Activity置于栈顶,获得焦点。
使用场景
应用主界面
![](https://img.haomeiwen.com/i6600660/fe56b770bfd9c443.png)
4.全局唯一模式singleInstance
1.在该模式下,我们会为目标Activity分配一个新的affinity,并创建一个新的Task栈,将目标Activity放入新的Task,并让目标Activity获得焦点。
2.新的Task有且只有这一个Activity实例。如果已经创建过目标Activity实例,则不会创建新的Task,而是将以前创建过的Activity唤醒(对应Task设为Foreground状态)。
3.具有全局唯一性和独占性
使用场景
拨打电话
![](https://img.haomeiwen.com/i6600660/2e14b335b11af79f.png)
网友评论