详解Android Activity生命周期

  Activity作为Android四大组件之首,在程序开发过程中扮演着非常重要的角色,是用户与程序之间进行交互的窗口.理解Activity的生命周期,有助于在开发过程中更好的进行控制逻辑处理.
  在Activity生命周期中,系统按照类似于金字塔一样的顺序去调用各个生命周期.当系统创建新的Activity实例时,每个回调方法将Activity状态向前移动一步,金字塔的顶部是Activity在前台运行的点,用户可以与之交互.

一 指定应用程序启动哪个Activity

  当用户选择进入应用程序后,系统会调用在程序声明中的Activity的onCreate()方法,这是程序与用户界面交互的入口.这个Activity必须在清单文件下进行声明:

注意:当程序创建一个新的Activity时,必须在Manifest.xml文件中进行声明

二 创建一个实例

  正常来讲,一个应用程序一般都会有几个Activity,不同Activity用来响应用户不同的操作,只要启动了该Activity,系统就会调用其onCreate()方法创建一个新的Activity实例.

1
2
3
4
5
6
7
8
9
10
11
TextView mTextView; // 布局中TextView的成员变量

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// 设置此活动的用户界面布局
// 布局文件在项目中定义res/layout/main_activity.xml
setContentView(R.layout.main_activity);
// 初始化成员TextView,以便我们以后可以操作它
mTextView = (TextView) findViewById(R.id.text_message);
}

上述代码中看到,在onCreate()方法中,首先应当给Activity设置相应的布局,然后对布局中的控件进行初始化操作.
  在onCreate()方法执行后,系统会连续执行onStart()和onResume()方法,Activity永远都不会处于”已创建”或者”已启动”状态.在调用onStart()时,Activity对用户来讲已经是可见状态,但执行onResume()方法后,Activity会快速保持在恢复状态,知道发生某些变化(接收电话,屏幕关闭)

三 Activity的销毁

  Activity的第一个生命周期回调时onCreate(),但它的最后一个回调是onDestory(),系统会将此Activity实例从内存中完全删除.

1
2
3
4
@Override
public void onDestroy() {
super.onDestroy();
}

  在onDestory方法中,应该将在onCreate()中创建的线程或者其他长时间的运行资源终止掉.(如果未正确关闭可能会引发内存泄漏).
注意:一般是在调用onPause()和onStop()之后调用onDestory(),但如果在程序在onCreate()方法中调用了finish()后,这种情况下,系统就会立即调用onDestory()而不调用其他任何生命周期方法

四 暂停和恢复Activity

  在正常的应用程序使用期间,应用程序有时会失去焦点,导致Activity暂停(例如,当应用程序在多窗口模式下运行时,任何时候只有一个应用程序具有焦点)
  当ACtivity进入暂停状态时,系统会调用onPause方法,这样就可以暂停不应继续执行的操作,或者是保留一些信息,如果用户从暂停状态回到Activity,系统将恢复并调用onResume()方法.

4.1 暂停当前Activity

当系统调用onPuse()方法时,它意味着Activity仍然部分可见,通常应该使用onPuase()回调来:
  ①检查Activity是否可见,如果不是,应该停止可能消耗CPU的动画或其他正在运行的操作,在Android7.0开始,多窗口模式下也可运行,这个时候就不需要暂停动画或者视频的播放;
  ② 提交未保存的更改,但前提是用户希望此类更改在离开时永久保存(例如草稿电子邮件);
  ③释放系统资源,例如广播接收器,处理传感器(如GPS),或在Activity暂停且用户不需要时可能影响电池寿命的任何资源。
例如:应用程序中使用Camera,在onPause()中释放

1
2
3
4
5
6
7
8
9
10
@Override
public void onPause() {
super.onPause();

// 释放相机,因为暂停时我们不需要它,而其他Activity可能需要使用它。
if (mCamera != null) {
mCamera.release();
mCamera = null;
}
}

注意:当Activity暂停时,Activity实例将保留在内存中,并在Activity恢复时调用。 不需要重新初始化组件。

4.2 恢复当前Activity

  当用户从暂停状态恢复时,系统将调用onResume()方法,因此程序需要在onResume()方法中来初始化onPuse()期间释放掉的组件。

1
2
3
4
5
6
7
8
9
@Override
public void onResume() {
super.onResume();
// 获取camera实例
if (mCamera == null) {
//初始化相机
initializeCamera();
}
}

五 停止并重新启动Activity

正确停止和重新启动Activity时Activity生命周期中一个重要的过程,Activity停止并重新启动的几种情况:
  ① 用户打开“最近的应用程序”窗口,并从当前应用程序切换到另一个应用时, 应用中当前位于前台的Activity已停止。 如果用户从主屏幕打开应用程序或从“最近的应用程序”窗口返回,则Activity将重新启动。
  ②当前Activity被新的Activity覆盖。创建第二个Activity时,将停止当前Activity。 如果用户然后按“返回”按钮,则重新启动第一个Activity。
  ③使用当前应用程序时会接到电话。
Activity提供了onStop()和onRestart()方法,它们用来处理Activity停止和重新启动的方式.与暂停状态不同的是,停止状态UI不在可见,并且用户的焦点位于单独的Activity中.

注意:当用户离开Activity时,系统调用onStop()来停止活动(1)。 如果用户在活动停止时返回,则系统调用onRestart()(2),然后快速调用onStart()(3)和onResume()(4)。 请注意,无论何种情况导致活动停止,系统始终在调用onStop()之前调用onPause()。

5.1 停止Activity

  当Activity收到对onStop()方法的调用时,它将不再可见,并且应该释放用户未使用时几乎所有不需要的资源。一旦Activity停止,系统可能会在需要恢复系统内存时销毁该实例。在极端情况下,系统可能只是在不调用Activity的onDestroy()回调的情况下杀死应用程序进程,因此使用onStop()释放可能泄漏内存的资源是可行的。
虽然在onStop()之前调用了onPause()方法,但是应该使用onStop()来执行更大,更密集的CPU关闭操作,例如将信息写入数据库。
例如,这是onStop()的一个实现,它将草稿注释的内容保存到持久存储:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@Override
protected void onStop() {
super.onStop();
// 保存笔记的当前草稿,因为Activity正在停止,我们希望确保当前笔记进度不会丢失。
ContentValues values = new ContentValues();
values.put(NotePad.Notes.COLUMN_NAME_NOTE, getCurrentNoteText());
values.put(NotePad.Notes.COLUMN_NAME_TITLE, getCurrentNoteTitle());

getContentResolver().update(
mUri,
values,
null,
null
);
}

5.2 重新启动Activity

  当Activity从停止状态返回到前台时,它会收到对onRestart()的调用。系统还调用onStart()方法,该方法在每次Activity可见时(无论是重新启动还是第一次创建)都会发生。但是,只有当Activity从停止状态恢复时才会调用onRestart()方法,因此可以使用它来执行特殊的恢复工作,这可能只有在Activity先前已停止但未被销毁时才需要。
  应用程序需要使用onRestart()来恢复Activity的状态并不常见,因此此方法没有适用于一般应用程序的任何准则。但是,因为onStop()方法应该基本上清理所有Activity的资源,所以当Activity重新启动时,需要重新实例化它们。 但是,当第一次创建Activity时(当没有Activity的现有实例时),还需要实例化它们。 因此,通常应该使用onStart()回调方法作为onStop()方法的对应方法,因为系统在创建活动时以及从停止状态重新启动活动时都会调用onStart()。

1
2
3
4
5
6
7
8
9
10
11
@Override
protected void onStart() {
super.onStart();
//活动要么重新启动,要么首次启动
}

@Override
protected void onRestart() {
super.onRestart();
// 从停止状态重新启动的活动
}

六 重新创建活动

  当Activity因用户按下Back或Activity自行完成而被销毁时,系统对该Activity实例的概念将永远消失,因为该行为表明不再需要该Activity。但是,如果系统因系统约束(而不是正常的应用程序行为)而破坏Activity,那么虽然实际的Activity实例已经消失,但系统会记住它存在,如果用户导航回到它,系统会创建一个新的Activity实例,使用一组保存的数据来描述销毁时的Activity状态。系统用于恢复先前状态的已保存数据称为“实例状态”,是存储在Bundle对象中的键值对的集合。
  要保存有关Activity状态的其他数据,必须覆盖onSaveInstanceState()回调方法。系统在用户离开Activity时调用此方法,并向其传递Bundle对象,该对象将在Activity意外销毁时保存。如果系统必须稍后重新创建Activity实例,它会将相同的Bundle对象传递给onRestoreInstanceState()和onCreate()方法。

6.1 保存Activity状态

  当Activity开始停止时,系统会调用onSaveInstanceState(),以便Activity可以使用一组键值对来保存状态信息。此方法的默认实现保存有关Activity视图层次结构状态的信息,例如EditText小部件中的文本或ListView的滚动位置。
要保存活动的其他状态信息,必须实现onSaveInstanceState()并将键值对添加到Bundle对象。 例如:

1
2
3
4
5
6
7
8
9
10
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);
}

6.2 恢复Activity状态

  在先前销毁活动之后重新创建活动时,您可以从系统传递活动的Bundle中恢复已保存的状态。 onCreate()和onRestoreInstanceState()回调方法都接收包含实例状态信息的相同Bundle。
  因为无论系统是创建活动的新实例还是重新创建前一个实例,都会调用onCreate()方法,因此在尝试读取之前必须检查状态Bundle是否为null。 如果它为null,则系统正在创建活动的新实例,而不是恢复已销毁的先前实例。
例如,以下是如何在onCreate()中恢复某些状态数据:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); // Always call the superclass first

// Check whether we're recreating a previously destroyed instance
if (savedInstanceState != null) {
// 从已保存状态恢复成员的值
mCurrentScore = savedInstanceState.getInt(STATE_SCORE);
mCurrentLevel = savedInstanceState.getInt(STATE_LEVEL);
} else {
// 可能使用新实例的默认值初始化成员
}

}

可以选择实现onRestoreInstanceState(),系统在onStart()方法之后调用on而不是在onCreate()期间恢复状态。 仅当存在要恢复的已保存状态时,系统才会调用onRestoreInstanceState(),因此您无需检查Bundle是否为null:

1
2
3
4
5
6
7
public void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);

// 从已保存的实例恢复状态成员
mCurrentScore = savedInstanceState.getInt(STATE_SCORE);
mCurrentLevel = savedInstanceState.getInt(STATE_LEVEL);
}

七 总结

Newer Post

使用CoordinatorLayout打造酷炫效果

#CoordinateLayout打造酷炫效果 一、CoordinatorLayout简介CoordinatorLayout是Android5.0之后推出的一个功能,它与AppBarLayout结合可以打造非常酷炫的效果.一般将CoordinatorLayout布局分为两部分,上半部分是AppBar …

继续阅读
Older Post

Android 自定义View

前言   首先我们先了解一下,什么叫view?Android官方文档对View的解释是这样的:表示用户界面组件的基本构建块,视图占据屏幕上的矩形区域,负责绘图和事件处理。以上可以看出view是程序与用户之间进行交互的桥梁。view的形状,大小,表现形式多种多样,所有就会发现And …

继续阅读