当用户浏览,退出和返回您的应用时,您应用中的活动实例会在其生命周期中的不同状态中进行转换。 Activity类提供了许多回调,允许活动知道状态已更改:系统正在创建,停止或恢复活动,或者破坏活动所在的进程。
在生命周期回调方法中,您可以声明用户离开并重新进入活动时活动的行为方式。例如,如果您正在构建流式视频播放器,则可能会在用户切换到另一个应用时暂停视频并终止网络连接。当用户返回时,您可以重新连接到网络并允许用户从同一位置恢复视频。换句话说,每个回调允许您执行适合于给定状态更改的特定工作。在正确的时间做正确的工作并正确处理过渡使您的应用程序更加强大和高效。例如,生命周期回调的良好实现可以帮助确保您的应用程序避免:
- 如果用户在使用您的应用程序时接到电话或切换到其他应用程序崩溃
- 当用户不主动使用它时,消耗宝贵的系统资源。
- 如果用户离开您的应用程序并在以后返回该应用程序时丢失该用户的进度。
- 当屏幕在横向和纵向之间旋转时,会崩溃或丢失用户的进度。
本文档详细说明了活动生命周期。 该文档首先描述了生命周期范例。 接下来,它解释了每个回调:执行时内部发生的事情,以及在它们期间应该实现的内容。 然后简要介绍了活动状态与进程被系统杀死的漏洞之间的关系。 最后,它讨论了与活动状态之间的转换相关的几个主题。
有关处理生命周期的信息,包括有关最佳实践的指导,请参阅使用生命周期感知组件处理生命周期和保存UI状态。 要了解如何使用与体系结构组件相结合的活动来构建强大的,生产质量的应用程序,请参阅应用程序体系结构指南。
一、活动 - 生命周期概念
为了在活动生命周期的各个阶段之间导航转换,Activity类提供了六个回调的核心集:onCreate(),onStart(),onResume(),onPause(),onStop()和onDestroy()。当活动进入新状态时,系统会调用每个回调。
图1展示了这种范例的直观表示。
当用户开始离开活动时,系统调用方法来拆除活动。在某些情况下,这种拆除只是部分的;活动仍然驻留在内存中(例如当用户切换到另一个应用程序时),并且仍然可以返回到前台。如果用户返回该活动,则活动将从用户停止的位置恢复。系统杀死给定进程的可能性以及其中的活动取决于当时活动的状态。活动状态和从内存中弹出提供了有关状态和弹出漏洞之间关系的更多信息。
根据活动的复杂程度,您可能不需要实现所有生命周期方法。但是,了解每一个并实施确保您的应用程序符合用户期望的行为非常重要。
本文档的下一部分提供了有关用于处理状态之间转换的回调的详细信息。
二、生命周期回调
本节提供有关在活动生命周期中使用的回调方法的概念和实现信息。
某些操作(例如调用setContentView())属于活动生命周期方法本身。 但是,实现依赖组件操作的代码应放在组件本身中。 要实现此目的,您必须使依赖组件生命周期可识别。 请参阅使用生命周期感知组件处理生命周期,以了解如何使依赖组件生命周期感知。
-
onCreate()
您必须实现此回调,该回调在系统首次创建活动时触发。在活动创建时,活动进入创建状态。在onCreate()方法中,您执行基本的应用程序启动逻辑,该逻辑在活动的整个生命周期中只应发生一次。例如,onCreate()的实现可能会将数据绑定到列表,将活动与ViewModel关联,并实例化一些类范围变量。此方法接收参数savedInstanceState,该参数是包含活动先前保存状态的Bundle对象。如果活动以前从未存在过,则Bundle对象的值为null。
如果您有一个生命周期感知组件连接到您的活动生命周期,它将收到ON_CREATE事件。将调用使用@OnLifecycleEvent注释的方法,以便您的生命周期感知组件可以执行创建状态所需的任何设置代码。
以下onCreate()方法示例显示了活动的基本设置,例如声明用户界面(在XML布局文件中定义),定义成员变量以及配置某些UI。在此示例中,通过将文件的资源ID R.layout.main_activity传递给setContentView()来指定XML布局文件。
extView mTextView;
// some transient state for the activity instance
String mGameState;
@Override
public void onCreate(Bundle savedInstanceState) {
// call the super class onCreate to complete the creation of activity like
// the view hierarchy
super.onCreate(savedInstanceState);
// recovering the instance state
if (savedInstanceState != null) {
mGameState = savedInstanceState.getString(GAME_STATE_KEY);
}
// set the user interface layout for this activity
// the layout file is defined in the project res/layout/main_activity.xml file
setContentView(R.layout.main_activity);
// initialize member TextView so we can manipulate it later
mTextView = (TextView) findViewById(R.id.text_view);
}
// This callback is called only when there is a saved instance that is previously saved by using
// onSaveInstanceState(). We restore some state in onCreate(), while we can optionally restore
// other state here, possibly usable after onStart() has completed.
// The savedInstanceState Bundle is same as the one used in onCreate().
@Override
public void onRestoreInstanceState(Bundle savedInstanceState) {
mTextView.setText(savedInstanceState.getString(TEXT_VIEW_KEY));
}
// invoked when the activity may be temporarily destroyed, save the instance state here
@Override
public void onSaveInstanceState(Bundle outState) {
outState.putString(GAME_STATE_KEY, mGameState);
outState.putString(TEXT_VIEW_KEY, mTextView.getText());
// call superclass to save any view hierarchy
super.onSaveInstanceState(outState);
}
作为定义XML文件并将其传递给setContentView()的替代方法,您可以在活动代码中创建新的View对象,并通过将新视图插入ViewGroup来构建视图层次结构。 然后,通过将根ViewGroup传递给setContentView()来使用该布局。 有关创建用户界面的更多信息,请参阅用户界面文档。
您的活动不在“已创建”状态。 onCreate()方法完成执行后,活动进入Started状态,系统快速连续调用onStart()和onResume()方法。 下一节将介绍onStart()回调。
onStart()
当活动进入Started状态时,系统将调用此回调。 onStart()调用使活动对用户可见,因为应用程序准备活动以进入前台并变为交互式。 例如,此方法是应用程序初始化维护UI的代码的位置。
当活动进入启动状态时,任何与活动生命周期相关的生命周期感知组件都将收到ON_START事件。
onStart()方法非常快速地完成,并且与Created状态一样,活动不会保持驻留在Started状态。 一旦此回调结束,活动就进入Resumed状态,系统将调用onResume()方法。onResume()
当活动进入Resumed状态时,它进入前台,然后系统调用onResume()回调。这是应用程序与用户交互的状态。该应用程序保持此状态,直到某些事情成为焦点远离应用程序。例如,这样的事件可能是接听电话,用户导航到另一个活动,或者设备屏幕关闭。
当活动进入恢复状态时,任何与活动生命周期相关的生命周期感知组件都将收到ON_RESUME事件。这是生命周期组件可以启用在组件可见且在前台时需要运行的任何功能的位置,例如启动摄像头预览。
发生中断事件时,活动进入暂停状态,系统调用onPause()回调。
如果活动从Paused状态返回Resumed状态,则系统再次调用onResume()方法。因此,您应该实现onResume()来初始化在onPause()期间释放的组件,并执行每次活动进入Resumed状态时必须进行的任何其他初始化。
以下是在组件收到ON_RESUME事件时访问摄像头的生命周期感知组件的示例:
public class CameraComponent implements LifecycleObserver {
...
@OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
public void initializeCamera() {
if (camera == null) {
getCamera();
}
}
...
}
一旦LifecycleObserver收到ON_RESUME事件,上面的代码就会初始化摄像机。但是,在多窗口模式下,即使活动处于暂停状态,您的活动也可能完全可见。例如,当用户处于多窗口模式并点击不包含您的活动的其他窗口时,您的活动将移至暂停状态。如果您希望仅在应用程序恢复时才激活相机(在前景中可见并处于活动状态),则在上面演示的ON_RESUME事件后初始化相机。如果要在活动暂停但是可见时(例如在多窗口模式下)保持相机处于活动状态,则应在ON_START事件后初始化相机。但请注意,在活动暂停时让相机处于活动状态可能会在多窗口模式下拒绝将相机访问另一个已恢复的应用程序。有时可能需要在活动暂停时保持相机处于活动状态,但如果这样做,实际上可能会降低整体用户体验。仔细考虑在生命周期中哪个位置更适合在多窗口环境中控制共享系统资源。要了解有关支持多窗口模式的更多信息,请参阅多窗口支持。
无论您选择在哪个构建事件中执行初始化操作,请确保使用相应的生命周期事件来释放资源。如果在ON_START事件之后初始化某些内容,则在ON_STOP事件之后释放或终止它。如果在ON_RESUME事件之后初始化,则在ON_PAUSE事件之后释放。
请注意,上面的代码片段将相机初始化代码放在生命周期感知组件中。您可以将此代码直接放入活动生命周期回调中,例如onStart()和onStop(),但不建议这样做。将此逻辑添加到独立的生命周期感知组件中,您可以跨多个活动重用该组件,而无需重复代码。请参阅使用生命周期感知组件处理生命周期以了解如何创建生命周期感知组件。
-
onPause()
系统将此方法称为用户离开您的活动的第一个指示(尽管并不总是意味着活动正在被销毁);它表示活动不再在前台(尽管如果用户处于多窗口模式,它仍然可见)。使用onPause()方法暂停或调整在“活动”处于“暂停”状态时不应继续(或应继续适度)的操作,并且您希望很快恢复。活动可能进入此状态的原因有多种。例如:
某些事件会中断应用程序执行,如onResume()部分所述。这是最常见的情况。
在Android 7.0(API级别24)或更高版本中,多个应用程序以多窗口模式运行。由于只有一个应用程序(窗口)可以随时关注,系统会暂停所有其他应用程序。
将打开一个新的半透明活动(例如对话框)。只要活动仍然部分可见但不是焦点,它仍然暂停。
当活动进入暂停状态时,任何与活动生命周期相关的生命周期感知组件都将收到ON_PAUSE事件。这是生命周期组件可以停止在组件不在前台时不需要运行的任何功能的地方,例如停止相机预览。
您还可以使用onPause()方法释放系统资源,处理传感器(如GPS),或者在您的活动暂停且用户不需要时可能影响电池寿命的任何资源。但是,如上面onResume()部分所述,如果处于多窗口模式,Paused活动仍然可以完全可见。因此,您应该考虑使用onStop()而不是onPause()来完全释放或调整与UI相关的资源和操作,以更好地支持多窗口模式。
下面对On_PAUSE事件做出反应的LifecycleObserver示例是上面ON_RESUME事件示例的对应示例,释放了在收到ON_RESUME事件后初始化的摄像头:
public class JavaCameraComponent implements LifecycleObserver {
...
@OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)
public void releaseCamera() {
if (camera != null) {
camera.release();
camera = null;
}
}
...
}
请注意,上面的代码片段在LifecycleObserver收到ON_PAUSE事件后放置了相机释放代码。如前所述,请参阅使用生命周期感知组件处理生命周期以了解如何创建生命周期感知组件。
onPause()执行非常简短,并且不一定能够提供足够的时间来执行保存操作。因此,您不应使用onPause()来保存应用程序或用户数据,进行网络调用或执行数据库事务;在方法完成之前,此类工作可能无法完成。相反,您应该在onStop()期间执行重负载关闭操作。有关在onStop()期间执行的合适操作的更多信息,请参阅onStop()。有关保存数据的更多信息,请参阅保存和恢复活动状态。
完成onPause()方法并不意味着活动离开Paused状态。相反,活动保持在此状态,直到活动恢复或对用户完全不可见。如果活动恢复,系统将再次调用onResume()回调。如果活动从Paused状态返回到Resumed状态,系统会将Activity实例驻留在内存中,在系统调用onResume()时调用该实例。在这种情况下,您无需重新初始化在任何导致Resumed状态的回调方法期间创建的组件。如果活动变得完全不可见,则系统调用onStop()。下一节将讨论onStop()回调。
-
onStop()
当您的活动不再对用户可见时,它已进入Stopped状态,系统将调用onStop()回调。例如,当新启动的活动覆盖整个屏幕时,可能会发生这种情况。当活动完成运行时,系统也可以调用onStop(),并且即将终止。
当活动进入停止状态时,任何与活动生命周期相关的生命周期感知组件都将收到ON_STOP事件。这是生命周期组件可以停止在组件在屏幕上不可见时不需要运行的任何功能的地方。
在onStop()方法中,应用程序应释放或调整应用程序对用户不可见时不需要的资源。例如,您的应用可能会暂停动画或从细粒度位置更新切换到粗粒度位置更新。使用onStop()而不是onPause()可确保与UI相关的工作继续进行,即使用户在多窗口模式下查看您的活动也是如此。
您还应该使用onStop()执行相对CPU密集型的关闭操作。例如,如果找不到更合适的时间将信息保存到数据库,则可以在onStop()期间执行此操作。以下示例显示了onStop()的实现,该实现将草稿注释的内容保存到持久存储:
@Override
protected void onStop() {
// call the superclass method first
super.onStop();
// save the note's current draft, because the activity is stopping
// and we want to be sure the current note progress isn't lost.
ContentValues values = new ContentValues();
values.put(NotePad.Notes.COLUMN_NAME_NOTE, getCurrentNoteText());
values.put(NotePad.Notes.COLUMN_NAME_TITLE, getCurrentNoteTitle());
// do this update in background on an AsyncQueryHandler or equivalent
mAsyncQueryHandler.startUpdate (
mToken, // int token to correlate calls
null, // cookie, not used here
mUri, // The URI for the note to update.
values, // The map of column names and new values to apply to them.
null, // No SELECT criteria are used.
null // No WHERE columns are used.
);
}
注意,上面的代码示例直接使用SQLite。 您应该使用Room,这是一个提供SQLite抽象层的持久性库。 要了解有关使用Room的好处以及如何在应用程序中实现Room的更多信息,请参阅Room Persistence Library指南。
当您的活动进入Stopped状态时,Activity对象将保留在内存中:它维护所有状态和成员信息,但不会附加到窗口管理器。 活动恢复后,活动会回忆此信息。 您不需要重新初始化在导致Resumed状态的任何回调方法期间创建的组件。 系统还会跟踪布局中每个View对象的当前状态,因此,如果用户在EditText小部件中输入文本,则会保留该内容,因此您无需保存和还原它。
注意:停止活动后,如果系统需要恢复内存,系统可能会破坏包含活动的进程。 即使系统在活动停止时销毁进程,系统仍会保留Bundle(一对键值对)中的View对象(例如EditText小部件中的文本)的状态,并在用户恢复它们时 导航回活动。 有关还原用户返回的活动的详细信息,请参阅保存和还原活动状态。
从Stopped状态,活动要么返回与用户交互,要么活动已完成运行并消失。 如果活动返回,系统将调用onRestart()。 如果Activity已完成运行,则系统将调用onDestroy()。 下一节将介绍onDestroy()回调。
-
onDestroy()
在销毁活动之前调用onDestroy()。 系统调用此回调因为:
- 活动正在结束(由于用户完全解雇活动或由于活动调用完成()),或
- 由于配置更改(例如设备旋转或多窗口模式),系统暂时销毁活动
当活动进入销毁状态时,任何与活动生命周期相关的生命周期感知组件都将收到ON_DESTROY事件。这是生命周期组件可以在销毁Activity之前清除所需的任何内容的地方。
您应该使用ViewModel对象来包含Activity的相关视图数据,而不是在您的Activity中放置逻辑以确定它被销毁的原因。如果由于配置更改而将重新创建Activity,则ViewModel不必执行任何操作,因为它将被保留并提供给下一个Activity实例。如果不重新创建Activity,则ViewModel将调用onCleared()方法,以便在销毁之前清除所需的任何数据。
您可以使用isFinishing()方法区分这两种情况。
如果活动正在完成,则onDestroy()是活动接收的最终生命周期回调。如果因配置更改而调用onDestroy(),系统会立即创建新的活动实例,然后在新配置中的新实例上调用onCreate()。
onDestroy()回调应释放早期回调(例如onStop())尚未释放的所有资源。
三、活动状态和从内存中弹出
系统在需要释放RAM时会终止进程; 系统杀死给定进程的可能性取决于当时进程的状态。 反过来,进程状态取决于进程中运行的活动的状态。 表1显示了进程状态,活动状态和系统终止进程的可能性之间的相关性。
流程生命周期与活动状态之间的关系
系统永远不会直接杀死活动以释放内存。 相反,它会杀死活动运行的过程,不仅会破坏活动,还会破坏流程中运行的所有其他活动。 要了解在系统启动的进程死亡发生时如何保留和恢复活动的UI状态,请参阅保存和恢复活动状态。
用户还可以使用“设置”下的“应用程序管理器”终止相应的应用程序。
有关一般进程的更多信息,请参阅进程和线程。 有关进程生命周期如何与其中活动状态相关联的更多信息,请参阅该页面的“进程生命周期”部分。
四、保存和恢复瞬态UI状态
用户期望活动的UI状态在整个配置更改期间保持不变,例如轮换或切换到多窗口模式。但是,系统会在发生此类配置更改时默认销毁活动,从而消除存储在活动实例中的任何UI状态。同样,用户希望UI状态保持不变,如果他们暂时从您的应用切换到其他应用,然后稍后再回到您的应用。但是,当用户离开并且您的活动停止时,系统可能会破坏您的应用程序的进程。
当活动因系统限制而被销毁时,您应该使用ViewModel,onSaveInstanceState()和/或本地存储的组合来保留用户的瞬态UI状态。要了解有关用户期望与系统行为的更多信息,以及如何在系统启动的活动和流程死亡中最好地保留复杂的UI状态数据,请参阅保存UI状态。
本节概述了实例状态以及如何实现onSaveInstance()方法,该方法是对活动本身的回调。如果您的UI数据简单而轻量级,例如原始数据类型或简单对象(如String),则可以单独使用onSaveInstanceState()来保持UI状态跨越配置更改和系统启动的进程死亡。但是,在大多数情况下,您应该使用ViewModel和onSaveInstanceState()(如保存UI状态中所述),因为onSaveInstanceState()会导致序列化/反序列化成本。
1、实例状态
在某些情况下,您的活动会因应用程序的正常行为而被销毁,例如当用户按下“返回”按钮或您的活动通过调用finish()方法发出自己的破坏信号时。当您的活动因用户按下Back或活动自行完成而被销毁时,系统和用户对该Activity实例的概念将永远消失。在这些情况下,用户的期望与系统的行为相匹配,您没有任何额外的工作要做。
但是,如果系统因系统约束(例如配置更改或内存压力)而破坏活动,则虽然实际的Activity实例已消失,但系统会记住它已存在。如果用户尝试导航回活动,系统将使用一组已保存的数据创建该活动的新实例,这些数据描述了活动在销毁时的状态。
系统用于恢复先前状态的已保存数据称为实例状态,是存储在Bundle对象中的键值对的集合。默认情况下,系统使用Bundle实例状态来保存活动布局中每个View对象的信息(例如输入EditText小部件的文本值)。因此,如果您的活动实例被销毁并重新创建,则布局的状态将恢复到之前的状态,而您不需要代码。但是,您的活动可能包含您要恢复的更多状态信息,例如跟踪用户在活动中的进度的成员变量。
注意:为了让Android系统恢复活动中视图的状态,每个视图必须具有唯一的ID,由android:id属性提供。
Bundle对象不适合保留超过一小部分数据,因为它需要在主线程上进行序列化并消耗系统进程内存。 要保留超过极少量的数据,您应该采用组合方法来保留数据,使用持久本地存储,onSaveInstanceState()方法和ViewModel类,如保存UI状态中所述。
2、使用onSaveInstanceState()保存简单,轻量级的UI状态
当您的活动开始停止时,系统会调用onSaveInstanceState()方法,以便您的活动可以将状态信息保存到实例状态包。 此方法的默认实现保存有关活动视图层次结构状态的瞬态信息,例如EditText小部件中的文本或ListView小部件的滚动位置。
要为活动保存其他实例状态信息,必须覆盖onSaveInstanceState()并将键值对添加到在活动意外销毁时保存的Bundle对象。 如果重写onSaveInstanceState(),则必须调用超类实现,如果希望默认实现保存视图层次结构的状态。 例如:
static final String STATE_SCORE = "playerScore";
static final String STATE_LEVEL = "playerLevel";
// ...
@Override
public void onSaveInstanceState(Bundle savedInstanceState) {
// Save the user's current game state
savedInstanceState.putInt(STATE_SCORE, mCurrentScore);
savedInstanceState.putInt(STATE_LEVEL, mCurrentLevel);
// Always call the superclass so it can save the view hierarchy state
super.onSaveInstanceState(savedInstanceState);
}
注意:当用户显式关闭活动时或在调用finish()的其他情况下,不会调用onSaveInstanceState()。
要保存持久性数据(例如用户首选项或数据库的数据),您应该在活动处于前台时采取适当的机会。 如果没有这样的机会,您应该在onStop()方法中保存这些数据。
3、使用已保存的实例状态还原活动UI状态
在先前销毁活动后重新创建活动时,可以从系统传递给活动的Bundle中恢复已保存的实例状态。 onCreate()和onRestoreInstanceState()回调方法都接收包含实例状态信息的相同Bundle。
因为无论系统是创建活动的新实例还是重新创建前一个实例,都会调用onCreate()方法,因此在尝试读取之前必须检查状态Bundle是否为null。 如果它为null,则系统正在创建活动的新实例,而不是恢复已销毁的先前实例。
例如,以下代码段显示了如何在onCreate()中恢复某些状态数据:
@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) {
// Restore value of members from saved state
mCurrentScore = savedInstanceState.getInt(STATE_SCORE);
mCurrentLevel = savedInstanceState.getInt(STATE_LEVEL);
} else {
// Probably initialize members with default values for a new instance
}
// ...
}
您可以选择实现onRestoreInstanceState(),系统在onStart()方法之后调用on而不是在onCreate()期间恢复状态。 仅当存在要恢复的已保存状态时,系统才会调用onRestoreInstanceState(),因此您无需检查Bundle是否为null:
public void onRestoreInstanceState(Bundle savedInstanceState) {
// Always call the superclass so it can restore the view hierarchy
super.onRestoreInstanceState(savedInstanceState);
// Restore state members from saved instance
mCurrentScore = savedInstanceState.getInt(STATE_SCORE);
mCurrentLevel = savedInstanceState.getInt(STATE_LEVEL);
}
警告:始终调用onRestoreInstanceState()的超类实现,以便默认实现可以恢复视图层次结构的状态。
四、在活动之间导航
在应用程序的生命周期中,应用程序很可能会多次进入和退出活动。 例如,用户可以点击设备的“后退”按钮,或者活动可能需要启动不同的活动。 本节介绍了实现成功的活动转换所需了解的主题。 这些主题包括从其他活动启动活动,保存活动状态以及恢复活动状态。
1、从另一个开始一个活动
活动通常需要在某个时刻开始另一项活动。 例如,当应用程序需要从当前屏幕移动到新屏幕时,就会出现这种需求。
根据您的活动是否希望从即将启动的新活动返回结果,您可以使用startActivity()或startActivityForResult()方法启动新活动。 在任何一种情况下,都传入一个Intent对象。
Intent对象指定要启动的确切活动或描述您要执行的操作类型(系统为您选择适当的活动,甚至可以来自不同的应用程序)。 Intent对象还可以携带少量数据以供启动的活动使用。 有关Intent类的更多信息,请参阅Intents和Intent Filters。
2、startActivity()
如果新启动的活动不需要返回结果,则当前活动可以通过调用startActivity()方法启动它。
在自己的应用程序中工作时,通常需要简单地启动已知活动。 例如,以下代码段显示了如何启动名为SignInActivity的活动。
Intent intent = new Intent(this, SignInActivity.class);
startActivity(intent);
您的应用程序可能还希望使用活动中的数据执行某些操作,例如发送电子邮件,短信或状态更新。 在这种情况下,您的应用程序可能没有自己的活动来执行此类操作,因此您可以利用设备上其他应用程序提供的活动,这些活动可以为您执行操作。 这是意图非常有价值的地方:您可以创建描述您要执行的操作的意图,系统从另一个应用程序启动相应的活动。 如果有多个活动可以处理意图,那么用户可以选择使用哪个活动。 例如,如果要允许用户发送电子邮件,可以创建以下意图:
Intent intent = new Intent(Intent.ACTION_SEND);
intent.putExtra(Intent.EXTRA_EMAIL, recipientArray);
startActivity(intent);
添加到intent中的EXTRA_EMAIL额外是电子邮件应发送到的电子邮件地址的字符串数组。 当电子邮件应用程序响应此意图时,它会读取extra中提供的字符串数组,并将它们放在电子邮件撰写表单的“to”字段中。 在这种情况下,电子邮件应用程序的活动开始,当用户完成后,您的活动将恢复。
3、startActivityForResult()
有时您希望在活动结束时从结果中获取结果。例如,您可以启动一项活动,让用户在联系人列表中选择一个人;当它结束时,它返回被选中的人。为此,请调用startActivityForResult(Intent,int)方法,其中integer参数标识调用。此标识符用于消除来自同一活动的多次startActivityForResult(Intent,int)调用之间的歧义。它不是全局标识符,不存在与其他应用程序或活动冲突的风险。结果通过onActivityResult(int,int,Intent)方法返回。
当子活动退出时,它可以调用setResult(int)将数据返回到其父级。子活动必须始终提供结果代码,该结果代码可以是标准结果RESULT_CANCELED,RESULT_OK或从RESULT_FIRST_USER开始的任何自定义值。此外,子活动可以选择返回包含所需的任何其他数据的Intent对象。父活动使用onActivityResult(int,int,Intent)方法以及父活动最初提供的整数标识符来接收信息。
如果子活动因任何原因(例如崩溃)失败,则父活动将收到代码为RESULT_CANCELED的结果。
public class MyActivity extends Activity {
// ...
static final int PICK_CONTACT_REQUEST = 0;
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_DPAD_CENTER) {
// When the user center presses, let them pick a contact.
startActivityForResult(
new Intent(Intent.ACTION_PICK,
new Uri("content://contacts")),
PICK_CONTACT_REQUEST);
return true;
}
return false;
}
protected void onActivityResult(int requestCode, int resultCode,
Intent data) {
if (requestCode == PICK_CONTACT_REQUEST) {
if (resultCode == RESULT_OK) {
// A contact was picked. Here we will just display it
// to the user.
startActivity(new Intent(Intent.ACTION_VIEW, data));
}
}
}
}
4、协调活动
当一个活动开始另一个活动时,它们都会经历生命周期转换 第一个活动停止运行并进入Paused或Stopped状态,同时创建另一个活动。 如果这些活动共享保存到光盘或其他地方的数据,则必须了解第一个活动在创建第二个活动之前未完全停止。 相反,启动第二个的过程与停止第一个过程重叠。
生命周期回调的顺序是明确定义的,特别是当两个活动在同一个进程(app)中而另一个正在启动另一个时。 以下是活动A启动活动B时发生的操作顺序:
(1)Activity A的onPause()方法执行。
(2)活动B的onCreate(),onStart()和onResume()方法按顺序执行。 (活动B现在具有用户关注点。)
(3)然后,如果活动A在屏幕上不再可见,则执行onStop()方法。
这种可预测的生命周期回调序列允许您管理从一个活动到另一个活动的信息转换。