了解Activity生命周期

本文深入探讨了Android应用开发中Activity的生命周期,包括从创建到销毁的不同状态及其回调方法。通过掌握这些回调方法,开发者能够有效管理资源,提升用户体验。

当用户浏览,退出和返回您的应用时,您应用中的activity实例会在其生命周期中的不同状态中进行转换。 Activity类提供了许多回调,允许activity知道状态已更改:系统正在创建,停止或恢复activity,或者销毁activity所在的进程。

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

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

本文档详细说明了活动生命周期。该文档首先描述了生命周期范例。 接下来,它解释了每个回调:执行时内部发生的事情,以及在它们期间应该实现的内容。 然后简要介绍了activity状态与进程被系统杀死的漏洞之间的关系。最后,它讨论了与活动状态之间的转换相关的几个主题。

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

Activity-生命周期概念

为了在活动生命周期的各个阶段之间导航转换,Activity类提供了六个回调的核心集:onCreate(),onStart(),onResume(),onPause(),onStop()和onDestroy()。 当activity进入新状态时,系统会调用每个回调。

图1展示了这种范例的直观表示。

图1.活动生命周期的简化图示。

当用户开始离开activity时,系统调用方法来拆除activity。在某些情况下,这种拆除只是部分的; activity仍然驻留在内存中(例如当用户切换到另一个应用程序时),并且仍然可以返回到前台。 如果用户返回该activity,则activity将从用户停止的位置恢复。系统杀死给定进程的可能性及其中的activity取决于当时activity的状态。activity状态和从内存中弹出提供了有关状态与弹出漏洞之间关系的更多信息。

根据activity的复杂程度,您可能不需要实现所有生命周期方法。 但是,了解每一个并实施确保您的应用程序按用户期望的方式运行的内容非常重要。

本文档的下一部分提供了有关用于处理状态之间转换的回调的详细信息。

生命周期回调

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

某些操作(如调用setContentView())属于活动生命周期方法本身。 但是,实现依赖组件操作的代码应放在组件本身中。要实现此目的,您必须使依赖组件生命周期可识别。 请参阅使用生命周期感知组件处理生命周期,以了解如何使您的从属组件生命周期感知。

onCreate()

 在activity创建时,活动进入创建状态。 在onCreate()方法中,您执行基本的应用程序启动逻辑,该逻辑在活动的整个生命周期中只应发生一次。 例如,onCreate()的实现可能会将数据绑定到列表,将activity与ViewModel相关联,并实例化一些类范围变量。 此方法接收参数savedInstanceState,该参数是包含activity先前保存状态的Bundle对象。 该参数是包含activity先前保存状态的Bundle对象。 如果activity以前从未存在过,则Bundle对象的值为null。

如果您有一个生命周期感知组件连接到您的活动的生命周期,它将收到ON_CREATE事件。 将调用使用@OnLifecycleEvent注释的方法,以便您的生命周期感知组件可以执行创建状态所需的任何设置代码。

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

KOTLIN

lateinit var textView: TextView

// some transient state for the activity instance
var gameState: String? = null

override fun onCreate(savedInstanceState: Bundle?) {
    // call the super class onCreate to complete the creation of activity like
    // the view hierarchy
    super.onCreate(savedInstanceState)

    // recovering the instance state
    gameState = 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.activity_main)

    // initialize member TextView so we can manipulate it later
    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 fun onRestoreInstanceState(savedInstanceState: Bundle?) {
    textView.text = savedInstanceState?.getString(TEXT_VIEW_KEY)
}

// invoked when the activity may be temporarily destroyed, save the instance state here
override fun onSaveInstanceState(outState: Bundle?) {
    outState?.run {
        putString(GAME_STATE_KEY, gameState)
        putString(TEXT_VIEW_KEY, textView.text.toString())
    }
    // call superclass to save any view hierarchy
    super.onSaveInstanceState(outState)
}

JAVA

TextView textView;

// some transient state for the activity instance
String gameState;

@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) {
        gameState = 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
    textView = (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) {
    textView.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, gameState);
    outState.putString(TEXT_VIEW_KEY, textView.getText());

    // call superclass to save any view hierarchy
    super.onSaveInstanceState(outState);
}

作为定义XML文件并将其传递给setContentView()的替代方法,您可以在activity代码中创建新的View对象,并通过将新视图插入ViewGroup来构建视图层次结构。  然后,通过将根ViewGroup传递给setContentView()来使用该布局。 有关创建用户界面的更多信息,请参阅用户界面文档。

您的activity不在“已创建”状态。onCreate()方法完成执行后,activity进入Started状态,系统快速连续调用onStart()和onResume()方法。 下一节将介绍onStart()回调。

onStart()

当活动进入Started状态时,系统将调用此回调。onStart()调用使activity对用户可见,因为应用程序准备activity以进入前台并变为交互式。例如,此方法是应用程序初始化维护UI的代码的位置。

当活动进入启动状态时,任何与活动生命周期相关的生命周期感知组件都将收到ON_START事件。

onStart()方法非常快速地完成,并且与Created状态一样,活动不会保持驻留在Started状态。 一旦此回调结束,活动就进入Resumed状态,系统将调用onResume()方法。

onResume()

当activity进入Resumed状态时,它进入前台,然后系统调用onResume()回调。这是应用程序与用户交互的状态。 该应用程序保持这种状态,直到某些事件成为焦点离开应用程序。例如,这样的事件可能是接收电话,用户导航到另一个活动,或者设备屏幕关闭。

当activity进入恢复状态时,任何与activity生命周期相关的生命周期感知组件都将收到ON_RESUME事件。  这是生命周期组件可以启用任何需要在组件可见且在前台运行时运行的功能的位置,例如启动摄像头预览。

当发生中断事件时,activity进入Paused状态,系统调用onPause()回调。

如果活动从Paused状态返回Resumed状态,则系统再次调用onResume()方法。因此,您应该实现onResume()来初始化在onPause()期间释放的组件,并执行每次活动进入Resumed状态时必须进行的任何其他初始化。

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

KOTLIN

class CameraComponent : LifecycleObserver {

    ...

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

    ...
}

JAVA

public class CameraComponent implements LifecycleObserver {

    ...

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

    ...
}

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

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

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

onPause()

  • 系统将此方法称为用户离开您的acitivity的第一个指示(尽管并不总是意味着acitivity正在被销毁); 它表示activity不再在前台(尽管如果用户处于多窗口模式,它仍然可见)。使用onPause()方法暂停或调整在“activity”处于“暂停”状态时不应继续(或应继续适度)的操作,并且您希望很快恢复。activity可能进入此状态的原因有多种。 例如:
  • 某些事件会中断应用程序执行,如onResume()部分所述。 这是最常见的情况。在Android 7.0(API级别24)或更高版本中,多个应用程序以多窗口模式运行。由于只有一个应用程序(窗口)可以随时关注,系统会暂停所有其他应用程序。

当activity进入暂停状态时,任何与activity生命周期相关的生命周期感知组件都将收到ON_PAUSE事件。  这是生命周期组件可以停止在组件不在前台时不需要运行的任何功能的地方,例如停止相机预览。

您还可以使用onPause()方法释放系统资源,处理传感器(如GPS),或者在您的activity暂停且用户不需要时可能影响电池寿命的任何资源。  但是,如上面onResume()部分所述,如果处于多窗口模式,Paused activity仍然可以完全可见。 因此,您应该考虑使用onStop()而不是onPause()来完全释放或调整与UI相关的资源和操作,以更好地支持多窗口模式。

下面对On_PAUSE事件做出反应的LifecycleObserver示例是上面ON_RESUME事件示例的对应示例,释放了在收到ON_RESUME事件后初始化的摄像头:

KOTLIN

class CameraComponent : LifecycleObserver {

    ...

    @OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)
    fun releaseCamera() {
        camera?.release()
        camera = null
    }

    ...
}

JAVA

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状态。

完成onPause()方法并不意味着activity离开Paused状态。 相反,activity保持在此状态,直到activity恢复或变得对用户完全不可见。如果activity恢复,系统将再次调用onResume()回调。 如果活动从Paused状态返回到Resumed状态,系统会将Activity实例驻留在内存中,在系统调用onResume()时调用该实例。 在这种情况下,您无需重新初始化在任何导致Resumed状态的回调方法期间创建的组件。 如果activity变得完全不可见,则系统调用onStop()。下一节讨论onStop()回调。

onStop()

 

转载于:https://www.cnblogs.com/bky1225987336/p/10639907.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值