一、Activity是什么
活动(Activity)是最容易吸引用户的地方,它是一种可以包含用户界面的组件,主要用于和用户进行交互。一个应用程序中可以包含零个或多个活动,但不包含任何活动的应用程序很少见,谁也不想让自己的应用永远无法被用户看到吧?————摘自《第一行代码》
二、Activity的四种状态
- running :活动状态,正在跟用户进行交互。
- paused:暂停状态,失去焦点。
- stopped:被另外一个 Activity 完全覆盖。
- killed:Activity 被系统回收掉。
三、Activity的生命周期
- Activity 第一次启动:
onCreate
、onStart
、onResume
。 - 点击 Home 键回到主界面:
onPause
、onStop
。 - 当我们再次回到 Activity:
onRestart
、onStart
、onResume
。 - 当退出当前 Activity:
onPause
、onStop
、onDestroy
。
回调 | 描述 |
---|---|
onCreate() | 这是第一个回调,在活动第一次创建时调用 |
onRestart() | 在当前活动重新显示给用户(用户已导航回该活动)之后调用。 |
onStart() | 这个回调在活动为用户可见时被调用 |
onResume() | 这个回调在应用程序与用户开始可交互的时候调用 |
onPause() | 被暂停的活动无法接受用户输入,不能执行任何代码。当前活动将要被暂停,上一个活动将要被恢复时调用 |
onStop() | 当活动不在可见时调用 |
onDestroy() | 当活动被系统销毁之前调用 |
四、生命周期过程演示
通过这个代码示例,形象化步骤用以展示 Android 应用程序活动的生命周期。还是用HelloWorld这个敲门砖进行加工展示。
下面是主要活动文件 java/com/example/myapplication/MainActivity.java
修改的内容。里面包含每一个基本的生命周期方法。Log.d()
方法用来生成日志信息:
package com.example.myapplication;
import android.os.Bundle;
import android.app.Activity;
import android.util.Log;
public class MainActivity extends AppCompatActivity {
String msg = "Android : ";
/** 当活动第一次被创建时调用 */
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Log.d(msg, "The onCreate() event");
}
/** 当活动重新显示时调用 */
@Override
protected void onRestart() {
super.onRestart();
Log.d(msg, "The onRestart() event");
}
/** 当活动即将可见时调用 */
@Override
protected void onStart() {
super.onStart();
Log.d(msg, "The onStart() event");
}
/** 当活动可见时调用 */
@Override
protected void onResume() {
super.onResume();
Log.d(msg, "The onResume() event");
}
/** 当其他活动获得焦点时调用 */
@Override
protected void onPause() {
super.onPause();
Log.d(msg, "The onPause() event");
}
/** 当活动不再可见时调用 */
@Override
protected void onStop() {
super.onStop();
Log.d(msg, "The onStop() event");
}
/** 当活动将被销毁时调用 */
@Override
public void onDestroy() {
super.onDestroy();
Log.d(msg, "The onDestroy() event");
}
}
点击启动后,可以在Logcat中看到日志信息,如果太多可以筛选;
点击 Home 键,将在 Logcat 窗口产生如下的事件消息;
点击菜单键,选选择 Activity 的页面,重新进入,将在 Logcat 窗口产生如下的事件消息;
点击返回键,退出到主界面,将在 Logcat 窗口产生如下的事件消息;
五、旋转屏幕引起 Activity 重建
默认情况下,在横竖屏切换的过程中,会发生 Activity 被销毁并重建的过程。 在了解这种情况下的生命周期时,首先应该了解这两个回调:onSaveInstanceState
和 onRestoreInstanceState
。
- 在 Activity 由于异常情况下终止时,系统会调用
onSaveInstanceState
来保存当前 Activity
的状态,该方法只在 Activity 被异常终止的情况下调用。 - 当异常终止的 Activity 被重建以后,系统会调用
onRestoreInstanceState
,并且把 Activity 销毁时
onSaveInstanceState
方法所保存的 Bundle 对象参数同时传递给onRestoreInstanceState
和
onCreate
方法。
因此,可以通过 onRestoreInstanceState
方法来恢复 Activity 的状态,该方法的调用时机是在 onStart
之后。其中 onCreate
和 onRestoreInstanceState
方法来恢复 Activity 的状态的区别: onRestoreInstanceState
回调则表明其中 Bundle 对象非空,不用加非空判断。onCreate
需要非空判断。建议使用 onRestoreInstanceState
。
如果 Activity 重建 onRestoreInstanceState
方法必定会被调用,onRestoreInstanceState
调用时机在 Activity 的 onStart
方法之后。调用链就在 ActivityThread 的 performLaunchActivity()
中的 mInstrumentation.callActivityOnRestoreInstanceState
。
横竖屏切换的生命周期:onPause()-> onStop()->onSaveInstanceState()->onDestroy()->onCreate()->onStart()->onRestoreInstanceState->onResume()
在清单文件中设置 configChanges 的属性为 orientation | screenSize。这时旋转屏幕后,Activity 并不会重建,取而代之的是调用 onConfigurationChanged() 方法。
六、Activity 的四种启动模式
- standard :创建 Activity,添加到任务栈中。每当启动一个新的活动,它就会在返回栈中入栈,并处于栈顶的位置。对于使用 standard 模式的活动,系统不会在乎这个活动是否已经在返回栈中存在,每次启动都会创建该活动的一个新的实例。
- singleTop:栈顶复用。如果启动的 Activity 在栈顶,那么 Activity 就不会被重新创建,而是回调它的
onNewIntent()
方法。如果不在栈顶,那么依然会被创建并添加到栈顶。在通知栏点击收到的通知,然后需要启动一个 Activity,这个 Activity 就可以用 singleTop,但 singleTop 启动模式并不是每次都有效。 - singleTask:每次启动该活动时系统首先会在返回栈中检查是否存在该活动的实例,如果发现已经存在则直接使用该实例,并把在这个活动之上的所有活动统统出栈,如果没有发现就会创建一个新的活动实例。
- singleinstance:作为栈内复用模式(singleTask)的加强版。 直接创建一个新的任务栈,并创建该 Activity 实例放入新栈中。一旦该模式的 Activity 实例已经存在于某个栈中,任何应用再激活该 Activity 时都会重用该栈中的实例。应用场景: 呼叫来电界面。这种模式的使用情况比较罕见,
需要注意一点的是,启动 Activity 的时候是将 Activity 放入其任务栈中,因此如果使用非 Activity 类型的 Context(如 ApplicationContext),那么启动的时候就会报错。解决的方案有两个:
- 不使用 ApplicationContext,传入对应的 Activity。
- 启动的时候添加
FLAG_ACTIVITY_NEW_TASK
标记。