【Android必备】Activity的生命周期(2)

了解Activity生命周期


当用户浏览,浏览并返回到您的应用程序时,应用程序中的 Activity实例将在其生命周期中的不同状态中转换。的Activity类提供了一些回调允许Activity知道一个状态已经改变的:该系统被创建,停止或恢复活性,或破坏该Activity所在的过程。

在生命周期回调方法中,您可以声明用户离开并重新进入Activity时Activity的行为。例如,如果您正在构建流媒体视频播放器,则可能会暂停视频并在用户切换到其他应用时终止网络连接。当用户返回时,您可以重新连接到网络并允许用户从同一地点恢复视频。换句话说,每个回调允许您执行适合于给定状态更改的特定工作。在正确的时间做适当的工作并正确地处理转换,可以使您的应用更加健壮和高效。例如,生命周期回调的良好实现可以帮助确保您的应用程序避免:

  • 如果用户在使用应用程序时收到电话或切换到其他应用程序,则会崩溃。
  • 当用户没有使用它时消耗宝贵的系统资源。
  • 如果用户离开您的应用程序并在稍后返回,则会丢失用户的进度。
  • 当屏幕在横向和纵向之间旋转时,会损坏或丢失用户的进度。

本文档详细解释了Activity生命周期。该文件从描述生命周期范式开始。接下来,它解释了每个回调:它们执行时在内部发生了什么,以及它们应该执行什么。然后简要介绍Activity状态与进程被系统杀死的脆弱性之间的关系。最后,它讨论了与Activity状态之间的转换有关的几个主题。

有关处理生命周期的信息(包括最佳实践指南),请参阅 使用生命周期感知组件处理生命周期以及保存UI状态。要了解如何使用与架构组件结合的Activity来构建强大的生产质量的应用程序,请参阅 应用程序架构指南

Activity生命周期概念


到的活性生命周期的阶段之间导航的过渡,Activity类别提供一组核心六个回调: onCreate(), onStart(), onResume(), onPause(), onStop(),和 onDestroy()。当Activity进入新状态时,系统调用每个回调。
【Android必备】Activity的生命周期(2)
图1展示了这种范例的视觉表现。
当用户开始离开Activity时,系统会调用方法来解除Activity。在某些情况下,这种拆除只是部分; 该Activity仍驻留在内存中(例如,当用户切换到另一个应用程序时),并且仍然可以回到前台。如果用户返回到该Activity,则该Activity从用户离开的地方恢复。系统杀死一个给定过程的可能性 - 以及其中的Activity - 取决于当时Activity的状态。Activity状态和记忆弹射提供了关于状态与弹射脆弱性之间关系的更多信息。

根据您的Activity的复杂程度,您可能不需要实施所有生命周期方法。但是,重要的是要了解每个人并实施那些可确保您的应用按用户期望的方式行事的人。

本文档的下一部分详细介绍了用于处理状态之间转换的回调。

生命周期回调


本节提供有关在Activity生命周期中使用的回调方法的概念和实现信息。

某些操作(如调用)属于Activity生命周期方法本身。但是,实现相关组件操作的代码应该放置在组件本身中。为了实现这一点,您必须使依赖组件的生命周期感知。请参阅 使用生命周期感知组件处理生命周期以了解如何使您的从属组件生命周期感知。 setContentView()

onCreate()

您必须实现此回调,当系统首次创建Activity时触发回调。在Activity创建时,Activity进入创建状态。在该onCreate() 方法中,您可以执行基本的应用程序启动逻辑,这些逻辑应该在Activity的整个生命周期中只发生一次。例如,您的实现可能会将数据绑定到列表,将该Activity与a关联 ,并实例化一些类作用域变量。此方法接收参数,该参数是 包含Activity先前保存状态的对象。如果Activity从未存在过,则该对象的值为空。 onCreate()ViewModelsavedInstanceStateBundleBundle

如果您有一个与生命周期相关的生命周期感知组件,它将收到该 ON_CREATE 事件。用@OnLifecycleEvent注解的方法将被调用,以便您的生命周期感知组件可以执行创建状态所需的任何设置代码。

下面的onCreate()方法示例 显示了该Activity的基本设置,例如声明用户界面(在XML布局文件中定义),定义成员变量以及配置一些UI。在这个例子中,XML布局文件是通过传递文件的资源ID R.layout.main_activity来 指定的setContentView()。

TextView 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在您的Activity代码中创建新对象,并通过将新的Views 插入到a中来 构建视图层次结构ViewGroup。然后通过传递根ViewGroup来 使用该布局setContentView()。有关创建用户界面的更多信息,请参阅 用户界面【原】文档。

您的Activity不处于创建状态。该onCreate()方法完成执行后,Activity进入启动 状态,系统将快速连续调用onStart() 和onResume()方法。下一节解释 onStart()回调。

onStart()

当Activity进入开始状态时,系统调用此回调。该onStart()调用使用户可以看到该Activity,因为该应用程序准备进入前台并成为交互式Activity。例如,此方法是应用程序初始化维护UI的代码的位置。

当Activity移动到开始状态时,与Activity生命周期关联的任何生命周期感知组件都将收到该 ON_START事件。

该onStart()方法非常快速地完成,并且与创建状态一样,该Activity不会保持驻留在已启动状态。一旦这个回调完成,Activity进入 恢复状态,系统调用该 onResume()方法。

onResume()

当Activity进入恢复状态时,它进入前台,然后系统调用onResume() 回调。这是应用程序与用户交互的状态。该应用停留在这种状态,直到发生某些事情将焦点从应用中移开。例如,这种事件可能是接到电话,用户导航到其他Activity或设备屏幕关闭。

当Activity转移到恢复状态时,与Activity生命周期关联的任何生命周期感知组件都将收到该 ON_RESUME 事件。这是生命周期组件可以在组件可见并且处于前台时启用需要运行的任何功能的位置,例如启动相机预览。
Activity
当发生中断事件时,ActivityActivity进入暂停 状态,系统调用 onPause()回调。

如果ActivityActivity从暂停状态返回到恢复状态,则系统再次调用 onResume()方法。因此,您应该实现onResume() 初始化您在释放期间发布的组件 onPause(),并执行每次Activity进入恢复状态时必须发生的任何其他初始化。

以下是组件接收ON_RESUME事件时访问摄像头的生命周期感知组件的示例 :

public class CameraComponent implements LifecycleObserver {

    ...

    @OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
    public void initializeCamera() {
        if (camera == null) {
            getCamera();
        }
    }

    ...
}

上面的代码初始化相机一次 LifecycleObserver 接收ON_RESUME事件。但是,在多窗口模式下,即使处于暂停状态,您的Activity也可以完全可见。例如,当用户处于多窗口模式并点击另一个不包含您的Activity的窗口时,您的Activity将移至暂停状态。如果您希望相机仅在应用程序恢复时处于Activity状态(在Activity前景中可见并处于Activity状态),请在上面显示的ON_RESUME事件之后初始化相机。如果您希望在Activity暂停但可见的情况下保持摄像机处于Activity状态(例如,在多窗口模式下),则应该在ON_START事件之后初始化摄像机。但请注意,如果在您的Activity暂停时让相机处于Activity状态,则可能会拒绝在多窗口模式下将相机访问到另一个恢复的应用程序。有时可能需要在您的ActivityActivity暂停时保持相机处于Activity状态,但如果您这样做,则实际上可能会降低整体用户体验。仔细考虑在生命周期的哪个地方更适合在多窗口环境中控制共享系统资源。要了解更多关于支持多窗口模式的信息,请参阅多窗口支持。

无论您选择在哪个构建事件中执行初始化操作,请确保使用相应的生命周期事件释放资源。如果您在ON_START事件之后初始化某些内容,请在ON_STOP事件之后释放或终止它。如果您在ON_RESUME事件之后进行初始化,请在ON_PAUSE事件之后释放。

请注意,上面的代码片段将摄像机初始化代码放置在生命周期感知组件中。您可以直接将此代码放入Activity生命周期回调中,例如 onStart(), onStop()但不建议这样做。将此逻辑添加到独立的支持生命周期的组件中,可让您跨多个Activity重用组件,而无需复制代码。请参阅 使用生命周期感知组件处理生命周期Activity 以了解如何创建生命周期感知组件。

onPause()

系统调用此方法作为用户离开Activity的第一个指示(尽管它并不总意味着Activity正在被销毁); 它表明该Activity不再处于前台(尽管如果用户处于多窗口模式,它仍然可见)。onPause()当Activity处于暂停状态时,使用该方法暂停或调整不应该继续(或者应该继续适度)的操作,并且您希望很快恢复。Activity可能会进入此状态有几个原因。例如:

  • 正如onResume()部分所述,某些事件会中断应用程序的执行。这是最常见的情况。
  • 在Android 7.0(API等级24)或更高版本中,多个应用程序以多窗口模式运行。因为任何时候只有其中一个应用程序(窗口)有焦点,系统会暂停所有其他应用程序。
  • 一个新的,半透明的Activity(如对话框)打开。只要该Activity仍然部分可见但不重点,它仍然处于暂停状态。

当Activity转到暂停状态时,与Activity生命周期关联的任何生命周期感知组件都将收到该 ON_PAUSE事件。这是生命周期组件可以停止在组件不在前台运行时不需要运行的任何功能的地方,例如停止相机预览。
Activity
您也可以使用此 onPause()方法释放系统资源,传感器的手柄(如GPS),或在Activity暂停并且用户不需要它们时可能影响电池寿命的任何资源。但是,如上面在onResume()部分中所述,如果在多窗口模式下,暂停的Activity仍可以完全可见。因此,您应该考虑使用onStop()而不是onPause()来完全释放或调整与UI相关的资源和操作,以更好地支持多窗口模式。

以下LifecycleObserver 响应ON_PAUSE事件的示例是上述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()。有关保存数据的更多信息,请参阅 保存和恢复Activity状态。

Activity该onPause()方法的完成并不意味着Activity离开暂停状态。而是,Activity保持这种状态,直到Activity恢复或对用户完全不可见为止。如果Activity恢复,系统再次调用onResume()回调。如果Activity从暂停状态返回到恢复状态,则系统将Activity实例驻留在内存中,并在系统调用时调用该实例 onResume()。在这种情况下,您不需要重新初始化任何导致恢复状态的回调方法中创建的组件。如果Activity完全不可见,则系统调用 onStop()。下一节讨论onStop()回调。

onStop()

当您的Activity对用户不再可见时,它已进入 停止状态,并且系统调用 onStop()回调。例如,当新推出的Activity覆盖整个屏幕时,可能会发生这种情况。系统也可能onStop() 在Activity完成并即将终止时调用。

当Activity进入停止状态时,与Activity生命周期关联的任何生命周期感知组件都将收到该 ON_STOP事件。这是生命周期组件可以停止在组件在屏幕上不可见时不需要运行的任何功能的地方。

在该onStop()方法中,应用程序应释放或调整应用程序对用户不可见时不需要的资源。例如,您的应用可能会暂停动画或从细粒度切换到粗粒度位置更新。 即使用户在多窗口模式下查看您的Activity,使用 onStop()而不是onPause()确保与用户界面相关的工作仍在继续。

您还应该使用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 指南。

当您的Activity进入停止状态时,该Activity 对象将保持驻留在内存中:它维护所有状态和成员信息,但未附加到窗口管理器。当Activity恢复时,Activity将回收此信息。您不需要重新初始化任何导致恢复状态的回调方法期间创建的组件。系统还会跟踪View布局中每个对象的当前状态,因此如果用户将文本输入到EditText小部件中,则会保留该内容,因此您无需保存和恢复它。

注意:一旦您的Activity停止,如果系统需要恢复内存,系统可能会销毁包含该Activity的进程。即使系统在Activity停止时销毁进程,系统仍然会将View 对象的状态(如EditText小部件中的文本)保留在 Bundle(一组键值对中),并在用户返回时恢复它们Activity。有关恢复用户返回的Activity的更多信息,请参阅 保存和恢复Activity状态。

从停止状态,Activity要么回到与用户交互,要么Activity完成运行并消失。如果Activity回来,系统会调用onRestart()。如果Activity完成运行,则系统调用 onDestroy()。下一节解释onDestroy() 回调。

onDestroy()

onDestroy()在Activity被破坏之前调用。系统调用此回调,因为:

  1. Activity正在完成(由于用户完全放弃Activity或由于 finish()被称为Activity),或者
  2. 系统会暂时破坏由于配置更改(如设备旋转或多窗口模式)导致的Activity,

当Activity进入停止状态时,与Activity生命周期关联的任何生命周期感知组件都将收到该 ON_DESTROY事件。这是生命周期组件在销毁Activity之前可以清理所需的任何内容的位置。

与其将逻辑放入您的Activity中以确定其销毁原因,您应该使用ViewModel对象来包含Activity的相关视图数据。如果Activity将因配置更改而重新创建,则ViewModel无需执行任何操作,因为它将被保留并提供给下一个Activity实例。如果Activity不会被重新创建,那么ViewModel将会onCleared()调用这个 方法,它可以在被销毁之前清理它需要的所有数据。

您可以使用该isFinishing()方法区分这两种情况 。

如果Activity正在结束,则onDestroy()是Activity接收的最终生命周期回调。如果onDestroy()作为配置更改的结果被调用,系统会立即创建一个新的Activity实例,然后 在新配置中调用 该新实例。 onCreate()

该onDestroy() 回调应释放还没有被释放由以前的回调,如所有资源onStop()。

Activity状态和从记忆中弹出


系统在需要释放RAM时会终止进程; 系统杀死给定进程的可能性取决于当时进程的状态。进程状态又取决于进程中运行的Activity的状态。表1显示了进程状态,Activity状态和系统杀死进程的可能性之间的相关性。
【Android必备】Activity的生命周期(2)
表1.流程生命周期与Activity状态之间的关系

系统不会直接杀死一个Activity来释放内存。相反,它会杀死Activity运行的过程,不仅会摧毁Activity,还会摧毁流程中运行的所有其他Activity。要了解在发生系统启动的进程死亡时如何保留和恢复Activity的UI状态,请参阅保存和恢复Activity状态。

用户也可以通过使用“设置”下的“应用程序管理器”来终止相应应用程序来终止进程。

有关一般进程的更多信息,请参阅 进程和线程。有关流程生命周期如何与其中的Activity状态关联的更多信息,请参阅该页面的 流程生命周期部分。

保存和恢复瞬态UI状态


用户期望Activity的UI状态在整个配置更改期间保持不变,例如旋转或切换到多窗口模式。但是,当这种配置更改发生时,系统会默认销毁Activity,并删除存储在Activity实例中的任何UI状态。同样,如果用户暂时将应用程序从应用程序切换到其他应用程序,然后再回到应用程序,用户希望UI状态保持不变。但是,当用户离开并且您的Activity停止时,系统可能会破坏您的应用程序的进程。

当Activity被破坏,由于系统的限制,你应该使用的组合保存用户的瞬时UI状态 ViewModel, 和/或本地存储。要了解有关用户期望与系统行为的更多信息,以及如何最好地保留跨系统启动的Activity和进程死亡的复杂UI状态数据,请参阅 保存UI状态。 onSaveInstanceState()

本节概述什么是实例状态,以及如何实现onSaveInstance()方法,这是对Activity本身的回调。如果您的UI数据是简单轻量的,比如原始数据类型或简单对象(如String),那么您可以单独使用onSaveInstanceState()来跨越配置更改和系统启动的进程终止来保持UI状态。不过,在大多数情况下,您应该使用ViewModel和onSaveInstanceState()(如 保存UI状态所述),因为onSaveInstanceState()会导致序列化/反序列化成本。

Activity实例状态

有几种情况会导致您的Activity由于正常的应用程序行为而遭到破坏,例如用户按下“后退”按钮或者您的Activity通过调用finish() 方法表示其自身销毁 。当您的Activity因用户按下“后退”或Activity自行完成而被销毁时,系统和用户对该Activity实例的概念都将永远消失。在这些情况下,用户的期望与系统的行为相匹配,并且您没有任何额外的工作要做。

但是,如果系统由于系统限制(例如配置更改或内存压力)而破坏Activity,则尽管实际 Activity 实例不存在,但系统还是会记住它存在。如果用户尝试导航回Activity,系统将使用一组保存的数据创建该Activity的新实例,该数据描述Activity在销毁时的状态。

系统用于恢复先前状态的已保存数据称为实例状态,是存储在Bundle对象中的键值对的集合。默认情况下,系统使用Bundle实例状态来保存有关ViewActivity布局中每个对象的信息(例如输入到EditText窗口小部件中的文本值 )。因此,如果您的Activity实例被销毁并重新创建,那么布局的状态将恢复到之前的状态,并且不需要您的代码。但是,您的Activity可能包含更多想要恢复的状态信息,例如跟踪用户Activity进度的成员变量。

注意:为了使Android系统恢复Activity中视图的状态,每个视图必须具有由android:id属性提供的唯一ID 。

一个Bundle对象不适合保存多余数量的数据,因为它需要在主线程上进行序列化并消耗系统进程内存。要保留超过极少量的数据,您应该采用综合方法来保存数据,使用持久本地存储, onSaveInstanceState() 方法和 类,如 保存UI状态所述。 ViewModel

使用onSaveInstanceState()保存简单轻量级的UI状态

当您的Activity开始停止时,系统会调用该 onSaveInstanceState() 方法,以便您的Activity可以将状态信息保存到实例状态包中。此方法的默认实现可以保存有关Activity视图层次结构状态的瞬态信息,例如EditText小部件中的文本或小部件的滚动位置 ListView。

为了保存Activity的其他实例状态信息,必须覆盖 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);
} 

Note: 当用户明确关闭Activity或在其他情况下调用时 不会调用finish(),则不会再调用 onSaveInstanceState()。

要保存持久性数据(例如用户首选项或数据库数据),当您的Activity处于前台时,应该采取适当的机会。如果没有这样的机会出现,您应该在该onStop()方法期间保存这些数据 。

使用保存的实例状态恢复Activity UI状态

当您的Activity在之前被销毁之后重新创建时,您可以从Bundle系统传递到您的Activity中恢复已保存的实例状态。无论是 onCreate()和 回调方法收到同样的 包含实例状态信息。 onRestoreInstanceState()Bundle

由于 调用方法是否系统正在创建Activity的新实例或重新创建前一个实例,因此必须在尝试读取状态之前检查状态Bundle是否为空。如果它为空,那么系统正在创建一个Activity的新实例,而不是恢复之前被销毁的实例。 onCreate()

例如,下面的代码片段显示了如何恢复一些状态数据: 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 
    } 
    // ... 
} 

您可以选择执行 ,而不是在系统调用方法之后 恢复状态 。系统 仅在存在保存状态才能恢复的情况下调用 ,因此不需要检查是否为空: onCreate() onRestoreInstanceState()onStart() onRestoreInstanceState()Bundle

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(), 以便默认实现可以恢复视图层次结构的状态

在Activity之间进行导航


应用程序可能会在应用程序的整个生命周期中进入或退出一个Activity,可能很多次。例如,用户可以点击设备的后退按钮,或者该Activity可能需要启动不同的Activity。本部分介绍实施成功Activity转换时需要了解的主题。这些主题包括从其他Activity开始Activity,保存Activity状态以及恢复Activity状态。

从另一个开始一个Activity

一个Activity通常需要在某个时候开始另一项Activity。例如,当应用程序需要从当前屏幕移动到新屏幕时,就会出现这种需求。

取决于您的Activity是否想要从新Activity返回的结果即将开始,您可以使用startActivity() 或 startActivityForResult() 方法开始新Activity 。无论哪种情况,您都会传入一个Intent对象。

该Intent对象指定要开始的确切Activity或描述您要执行的操作的类型(并且系统会为您选择适当的Activity,甚至可能来自不同的应用程序)。一个Intent对象还可以携带少量的数据供启动的Activity使用。有关Intent该类的更多信息,请参阅 Intents和Intent Filters

startActivity()

如果新开始的Activity不需要返回结果,则当前Activity可以通过调用该startActivity() 方法来启动它 。

在您的应用程序中工作时,您经常需要简单地启动已知的Activity。例如,以下代码片段显示了如何启动一个名为的Activity SignInActivity。

Intent intent = new Intent(this, SignInActivity.class);
startActivity(intent);

您的应用程序可能还希望使用您的Activity中的数据执行某些操作,例如发送电子邮件,短信或状态更新。在这种情况下,您的应用程序可能没有自己的Activity来执行此类操作,因此您可以利用设备上的其他应用程序提供的Activity,它们可以为您执行操作。这就是意图真正有价值的地方:您可以创建一个描述您想要执行的操作的意图,并且系统从另一个应用程序启动相应的Activity。如果有多个Activity可以处理意图,那么用户可以选择Activity使用哪一个。例如,如果您想允许用户发送电子邮件,则可以创建以下意向:

Intent intent = new Intent(Intent.ACTION_SEND);
intent.putExtra(Intent.EXTRA_EMAIL, recipientArray);
startActivity(intent);

在EXTRA_EMAIL加入额外的意图是该电子邮件应该发送电子邮件地址的字符串数组。当一个电子邮件应用程序响应这个意图时,它读取额外提供的字符串数组,并将它们放在电子邮件组合表单的“to”字段中。在这种情况下,电子邮件应用程序的Activity开始,当用户完成时,Activity恢复。

startActivityForResult()

有时您想在Activity结束时从Activity中取回结果。例如,您可以开始一项Activity,让用户在联系人列表中选择一个人; 当它结束时,它返回被选中的人。为此,您可以调用 startActivityForResult(Intent, int) 方法,其中integer参数标识调用。此标识符旨在消除startActivityForResult(Intent, int) 来自同一Activity的多个呼叫之间的歧义 。它不是全局标识符,不会与其他应用程序或Activity发生冲突。结果通过您的onActivityResult(int, int, Intent) 方法返回 。Activity

当一个孩子Activity退出时,它可以调用setResult(int)将数据返回给其父代。儿童Activity必须始终提供结果代码(可以是标准结果 RESULT_CANCELED)RESULT_OK,或者提供任何自定义值开始RESULT_FIRST_USER。另外,子Activity可以选择返回一个Intent 包含它想要的其他数据的对象。父Activity使用该 onActivityResult(int, int, Intent) 方法以及最初提供的父Activity的整数标识符来接收信息。

如果某个子Activity由于某种原因(例如崩溃)而失败,那么父Activity就会收到包含该代码的结果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));
             } 
         } 
     } 
 } 

协调Activity

当一项Activity开始另一项Activity时,它们都会经历生命周期转换。第一个Activity停止操作并进入暂停或停止状态,而另一个Activity则被创建。如果这些Activity共享保存在光盘或其他地方的数据,重要的是要明白,第一个Activity在创建第二个Activity之前尚未完全停止。相反,启动第二个过程的过程与停止第一个过程的过程重叠。

生命周期回调的顺序已被很好地定义,特别是当两个Activity处于同一个进程(应用程序)并且一个正在启动另一个时。以下是Activity A启动Activity B时发生的操作顺序:

  1. Activity A的onPause()方法执行。
  2. Activity B的onCreate(), onStart()和 onResume()方法按顺序执行。(Activity B现在有用户焦点。)
  3. 然后,如果Activity ActivityA在屏幕上不再可见,则onStop()执行其方法。

这种可预测的生命周期回调序列允许您管理从一个Activity到另一个Activity的信息转换。

Lastest Update:2018.05.18

Activity目录介绍

联系我

QQ:94297366
微信打赏:https://pan.baidu.com/s/1dSBXk3eFZu3mAMkw3xu9KQ

公众号推荐:

【Android必备】Activity的生命周期(2)

猜你喜欢

转载自blog.51cto.com/4789781/2122329