一. Android 四大组件包括
- Activity 活动
- Service 服务
- Broadcast Receiver 广播接收者
- Content Provider 内容提供者
1.什么是Activity?
用户可与其提供的屏幕进行交互,以执行拨打电话、拍摄照片、发送电子邮件或查看地图等操作。 每个 Activity 都会获得一个用于绘制其用户界面的窗口。窗口通常会充满屏幕,但也可小于屏幕并浮动在其他窗口之上。
2.正常情况下生命周期的分析
- onCreate()
表示Activity正在被创建,生命周期的第一个方法。进行一些初始化工作。 - onRestart()
表示Activity正在重新启动,一般表示当前不可见变为可见时,调用。(例:用户按了Home键后重新进入APP)。 - onStart()
表示Activity正在被启动,状态可见当不可与用户进行交互。 - onResume()
表示Activity已经可见并可与用户进行交互。 - onPause()
表示Activity正在被停止,正常情况下onSop()紧接着执行。此时可以执行一些短耗时的数据存贮等操作。可见不可交互。 - onStop()
表示Activity即将停止。不可见,可进行回收操作。 - onDestroy()
表示Activity即将被销毁,生命周期的最后一个回调方法。
针对如上描述,引入一张官方生命周期的图,更加直观的体现:
针对一个特定的Activity,每种不同条件下的回调如下:
-
第一次启动:onCreate()->onStart()->onResume()
-
退回桌面或者打开新的Activity:onPause()->onStop()
?:新的Activity采用透明主题,那么当前Activity不会回调onStop() -
再次回到Activity:onRestart()->onStart()->onResume()
-
back回退时:onPause()->onStop()->onDestroy()
-
界面跳转时:旧的Activity先执行onPause()后,新的Activity的才能创建并启动。
接下来我们去代码中实践一下,看看结果:
class MainActivity : AppCompatActivity() {
private val TAG = "wdl"
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
Log.d(TAG,"--onCreate--")
}
override fun onRestart() {
super.onRestart()
Log.d(TAG,"--onRestart--")
}
override fun onStart() {
super.onStart()
Log.d(TAG,"--onStart--")
}
override fun onResume() {
super.onResume()
Log.d(TAG,"--onResume--")
}
override fun onPause() {
super.onPause()
Log.d(TAG,"--onPause--")
}
override fun onStop() {
super.onStop()
Log.d(TAG,"--onStop--")
}
override fun onDestroy() {
super.onDestroy()
Log.d(TAG,"--onDestroy--")
}
}
第一次启动:
退回桌面:
再次回到界面:
回退:
3.异常情况下生命周期的分析
-
资源相关的系统配置发生改变导致Activity被杀死并重新创建
例:屏幕突然旋转,由于系统发生了改变。默认情况下Activity就会被销毁并且重新创建。
**在Activity意外终止时,会回调onPause(),onStop(),onDestroy()。在onStop之前会调用onSaveInstanceState方法保存当前Activity的状态。重建后调用onRestoreInstanceState方法并且把保存的Bundle传递给onCreateonRestoreInstanceState取出并恢复。onRestoreInstanceState在onStart后调用。**
class MainActivity : AppCompatActivity() {
private val TAG = "wdl"
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
Log.d(TAG, "--onCreate--")
if (savedInstanceState != null) {
val context = savedInstanceState.getString("test")
Log.d(TAG, "--$context--")
}
}
override fun onSaveInstanceState(outState: Bundle?) {
super.onSaveInstanceState(outState)
Log.d(TAG, "--onSaveInstanceState--")
outState!!.putString("test", "wdlwdlwdl")
}
override fun onRestart() {
super.onRestart()
Log.d(TAG, "--onRestart--")
}
override fun onStart() {
super.onStart()
Log.d(TAG, "--onStart--")
}
override fun onRestoreInstanceState(savedInstanceState: Bundle?) {
super.onRestoreInstanceState(savedInstanceState)
val context = savedInstanceState!!.getString("test")
Log.d(TAG, "--onRestoreInstanceState:$context--")
}
override fun onResume() {
super.onResume()
Log.d(TAG, "--onResume--")
}
override fun onPause() {
super.onPause()
Log.d(TAG, "--onPause--")
}
override fun onStop() {
super.onStop()
Log.d(TAG, "--onStop--")
}
override fun onDestroy() {
super.onDestroy()
Log.d(TAG, "--onDestroy--")
}
}
效果:
-屏幕竖直方向:
-旋转为水平方向:
2. 资源内存不足导致低优先级Activity被杀死
数据存贮和恢复过程与第一种一致。
Activity按照优先级从高到低可以分为一下三类:
- 前台Activity,正在和用户交互,优先级最高
- 可见但非前台–即无法与用户交互(弹出对话框等)
- 后台Activity,已经暂停的Activity,执行了onStop,优先级最低
如不想因为屏幕旋转而重新创建Activity,在AndroidManifest.xml中相应的配置上加上
android:configChanges="orientation|screenSize"
android:configChanges的(常用)值及其含义:
值 | 含义 |
---|---|
locale | 本地位置发生改变,即语言发生变化 |
keyboardHidder | 键盘可访问性发生改变 |
orientation | 屏幕方向发生改变 |
screenSize | 屏幕尺寸信息发生改变,API13新增,高于13时不添加,屏幕旋转会导致Activity重启 |
<activity android:name=".MainActivity"
android:configChanges="orientation|screenSize">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
Activity中新增:
override fun onConfigurationChanged(newConfig: Configuration?) {
super.onConfigurationChanged(newConfig)
Log.d(TAG, "--onConfigurationChanged:${newConfig!!.orientation}--")
}
监听屏幕旋转时的回调:
可以看到当配置了android:configChanges="orientation|screenSize"属性之后,再次进行屏幕旋转,Activity并未进行重建,从图中可以看到,只是方向发生了改变。
特别注意
在调用startActivityForResult()
下,setResult()
的调用时机应该是在finish()
回调方法之前,在onPause()
中调用setResult()
无法获取intent值,整体回调的过程如图:(因此我们需要在返回键按下时setResult()并且finish()本身)。