Understand the Activity Lifecycle(Activity(2))

As a user navigates through, out of, and back to your app, the Activity instances in your app transition through different states in their lifecycle. The Activity class provides a number of callbacks that allow the activity to know that a state has changed: that the system is creating, stopping, or resuming an activity, or destroying the process in which the activity resides.

当用户使用,跳出,或者返回你的app,activity会处于不同的状态。activity提供了一系列的回调函数,允许activity知道它的状态已经变化。

Within the lifecycle callback methods, you can declare how your activity behaves when the user leaves and re-enters the activity. For example, if you're building a streaming video player, you might pause the video and terminate the network connection when the user switches to another app. When the user returns, you can reconnect to the network and allow the user to resume the video from the same spot. In other words, each callback allows you to perform specific work that's appropriate to a given change of state. Doing the right work at the right time and handling transitions properly make your app more robust and performant. For example, good implementation of the lifecycle callbacks can help ensure that your app avoids:

在生命周期回调函数中,你可以声明当用户离开或再次回来时,activity的表现。比如,如果你正在播放一个video,你也许会在用户切到其他的app的时候,暂停video,同时停止网络链接。当用户回来时,你会重连网络,允许用户恢复video到用户离开时的状态。从另一方面来说,每一个回调函数都允许你在适当的生命周期中做一些特定的工作。在正确的事件做正确的事,并且合适地处理过渡将会使你的app变得更加健壮和优秀。比如良好地处理生命周期可以避免你的app发生以下状况:

(1)在用户接到电话或换到了其他的app,你的app会崩溃。

(2)当用户没有使用app的时候,会耗费宝贵的系统资源。

(3)如果用户离开app,并在稍后返回的时候,失去了用户的状态。

(4)当屏幕在横屏和竖屏之间旋转的时候,丢失用户的数据,或者直接崩溃。

  • Crashing if the user receives a phone call or switches to another app while using your app.
  • Consuming valuable system resources when the user is not actively using it.
  • Losing the user's progress if they leave your app and return to it at a later time.
  • Crashing or losing the user's progress when the screen rotates between landscape and portrait orientation.

This document explains the activity lifecycle in detail. The document begins by describing the lifecycle paradigm(范例). Next, it explains each of the callbacks: what happens internally while they execute, and what you should implement during them. It then briefly introduces the relationship between activity state and a process’s(进程) vulnerability(脆弱性) to being killed by the system. Last, it discusses several topics related to transitions between activity states.

该文档详细地解释了activity的生命周期,先介绍生命周期的例子,然后解释每一个回调函数:在他们执行的时候,正在发生什么,与你在这期间应该干些什么。然后简短地介绍activity生命周期状态之间的关系,以及进程被系统杀死的脆弱性。最后,讨论了activity状态之间的几个重点。

For information about handling lifecycles, including guidance about best practices, see Handling Lifecycles with Lifecycle-Aware Components and Saving UI States. To learn how to architect a robust, production-quality app using activities in combination with architecture components, see Guide to App Architecture.

对于如何处理LifeCycle,包括一些最佳实践的引导, Handling Lifecycles with Lifecycle-Aware Components and Saving UI States。学习如何结合activity和一些架构组件,才能构建一个健壮,可靠的app,参考Guide to App Architecture.

Activity-lifecycle concepts

To navigate transitions between stages of the activity lifecycle, the Activity class provides a core set of six callbacks: onCreate()onStart()onResume()onPause()onStop(), and onDestroy(). The system invokes each of these callbacks as an activity enters a new state.

Activity会在它自己进入一个新的状态的时候,调用相应的回调函数。

As the user begins to leave the activity, the system calls methods to dismantle(拆除) the activity. In some cases, this dismantlement is only partial(部分地); the activity still resides in memory (such as when the user switches to another app), and can still come back to the foreground. If the user returns to that activity, the activity resumes from where the user left off. With a few exceptions, apps are restricted from starting activities when running in the background(后台).

当用户准备离开activity的时候,系统会回调方法来清除activity。从某些方面来说,这个清楚只是部分地。activity仍然会有一部分留存在内存当中(比如当用户切换至另一个app的情况下),且仍然可以让activity回到前台。如果用户返回该activity,activity会恢复至用户离开时的状态。会有一些特殊的状态下,app在后台运行的时候,会限制启动activity。

The system’s likelihood of killing a given process—along with the activities in it—depends on the state of the activity at the time. Activity state and ejection (弹出)from memory provides more information on the relationship between state and vulnerability (脆弱性)to ejection.

系统可能会杀掉某个进程(包括进程中的所有activity),决定于activity当时所处的状态。activity的状态和从内存中弹出可以提供更多关于actiivty的状态,

Depending on the complexity of your activity, you probably don't need to implement all the lifecycle methods. However, it's important that you understand each one and implement those that ensure your app behaves the way users expect.

需不需要实现所有的生命周期回调函数,取决于你的activity有多复杂。即使如此,清楚每一个回调函数,和实现他们来保证这是用户想要的方式也是非常重要的。

The next section of this document provides detail on the callbacks that you use to handle transitions between states.

这个文档的下一节会提供更多关于回调函数,和你应该怎么处理关于状态切换的细节。

Lifecycle callbacks

This section provides conceptual and implementation information about the callback methods used during the activity lifecycle.

Some actions, such as calling setContentView(), belong in the activity lifecycle methods themselves. However, the code implementing the actions of a dependent component should be placed in the component itself. To achieve this, you must make the dependent component lifecycle-aware. See Handling Lifecycles with Lifecycle-Aware Components to learn how to make your dependent components lifecycle-aware.

这一节提供了在activity的生命周期中那些回调函数的概念性的和实现的信息。

一些操作,比如调用setContentView(),是属于activity的生命周期他们自己的操作。然而,那些实现一个独立部分的操作的代码应该被放置在那个模块自己的身上。为了达到这个目的,你必须使这些独立的模块可以清楚自己的生命周期。看Handling Lifecycles with Lifecycle-Aware Components 可以学习如何使那些独立的模块变得可以对自己的生命周期负责。

onCreate()

You must implement this callback, which fires when the system first creates the activity. On activity creation, the activity enters the Created state. In the onCreate() method, you perform basic application startup logic that should happen only once for the entire life of the activity. For example, your implementation of onCreate() might bind data to lists, associate the activity with a ViewModel, and instantiate some class-scope variables. This method receives the parameter savedInstanceState, which is a Bundle object containing the activity's previously saved state. If the activity has never existed before, the value of the Bundle object is null.

你必须实现这个回调函数,这会在系统第一次创建activity的时候被调用。一旦activity被创建了,它就进入了created的状态。在onCreate()方法中,你应该实现一些那些只会在activity的整个生命周期内执行一次的初始的逻辑操作。比如:你也许会在onCreate里面绑定列表的数据,将activity与viewmodel绑定,初始化一些局部变量。这个方法会得到savedInstanceState的参数,这个参数是Bundle类型的,包含了activity上一次保存的状态。如果这个activity之前没有存在过,那么这个Bundle的值就是null。

If you have a lifecycle-aware component that is hooked up to the lifecycle of your activity it will receive the ON_CREATE event. The method annotated with @OnLifecycleEvent will be called so your lifecycle-aware component can perform any setup code it needs for the created state.

如果你有一个生命周期感知的组件,且与你的activity的生命周期相绑定,那么它会得到ONCREATE的事件。这个被@OnLifecycleEvent注解的方法将会被调用,因此你的这个生命周期感知的组件将会执行相应的需要在created状态初始化的操作。

The following example of the onCreate() method shows fundamental setup for the activity, such as declaring the user interface (defined in an XML layout file), defining member variables, and configuring some of the UI. In this example, the XML layout file is specified by passing file’s resource ID R.layout.main_activity to setContentView().

下面的onCreate方法的代码将会展示activity的一些重要的初始化,比如声明用户界面,定义成员变量,配置UI的一些相关操作。在这个例子里,xml的布局文件是通过传递文件的资源id:R.layout.main_acitivity给setContentView的。

KOTLINJAVA

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);
}

 

As an alternative to defining the XML file and passing it to setContentView(), you can create new View objects in your activity code and build a view hierarchy by inserting new Views into a ViewGroup. You then use that layout by passing the root ViewGroup to setContentView(). For more information about creating a user interface, see the User Interface documentation.

将布局放进xml文件,并且将它传递给setContentView()只是一个选项,你同样可以创建新的view objects在activity内,同时通过将view插进viewgroup里面,构建一个view的层次结构,然后再将viewgroup塞进setContentView()里面。关于创建用户界面更多的信息,可以参考User Interface 的文档。

Your activity does not reside in (留在)the Created state. After the onCreate() method finishes execution, the activity enters the Started state, and the system calls the onStart() and onResume() methods in quick succession. The next section explains the onStart() callback.

你的activity不会在created状态中暂停。在onCreate()方法执行完了以后,activity会进入started的状态,同时系统会非常迅速地调用onStart()和onResume()方法。下一节将会解释onStart()回调函数。

onStart()

When the activity enters the Started state, the system invokes this callback. The onStart() call makes the activity visible to the user, as the app prepares for the activity to enter the foreground and become interactive. For example, this method is where the app initializes the code that maintains the UI.

当activity进入了started的状态,系统调用了这个回调函数。onStart()会使activity对用户可见,使activity进到前台并且变得可交互。比如说,这个方法就是app初始化关于ui的代码。

When the activity moves to the started state, any lifecycle-aware component tied to the activity's lifecycle will receive the ON_START event.

The onStart() method completes very quickly and, as with the Created state, the activity does not stay resident in the Started state. Once this callback finishes, the activity enters the Resumed state, and the system invokes the onResume() method.

当actiivity进入started状态,绑定了actiivty的生命周期的生命周期感知的组件将会接收到ON_START事件。

onStart方法会完成得非常迅速,同created的状态一样,actiivty不会停留在started的状态。一旦回调函数执行完成,activity就会进入到resumed的状态,同时调用onResume的方法。

onResume()

When the activity enters the Resumed state, it comes to the foreground, and then the system invokes the onResume() callback. This is the state in which the app interacts with the user. The app stays in this state until something happens to take focus away from the app. Such an event might be, for instance, receiving a phone call, the user’s navigating to another activity, or the device screen’s turning off.

当activity进入resumed的状态,activity就已经进入了前台,然后系统会调用onResume的回调函数。这是app与用户交互所处的状态,app会一直停留在这个状态, 知道app在某种情况下失去了焦点。这个事件也许会是:接到了一个电话,那么用户就会调转到另一个activity,或者设备屏幕关闭。

When the activity moves to the resumed state, any lifecycle-aware component tied to the activity's lifecycle will receive the ON_RESUME event. This is where the lifecycle components can enable any functionality that needs to run while the component is visible and in the foreground, such as starting a camera preview.

当activity的状态变成了resumed,任意绑定了actiivty的生命周期的生命周期感知组件都会接收到ON_RESUME事件。组件应该在此处处理那些需要actiivty为可见状态的事情,比如开始一个camera的相机预览。

When an interruptive event occurs, the activity enters the Paused state, and the system invokes the onPause() callback.

If the activity returns to the Resumed state from the Paused state, the system once again calls onResume() method. For this reason, you should implement onResume() to initialize components that you release during onPause(), and perform any other initializations that must occur each time the activity enters the Resumed state.

当发生中断事件时,actiivty会进入Paused状态,这时候,系统会调用onPause()方法。

如果actiivty从paused的状态回到resumed状态,系统会再次调用onResume方法。由此可知,在onResume方法初始化的组件应该在onPause方法释放。

Here is an example of a lifecycle-aware component that accesses the camera when the component receives the ON_RESUME event:

这是一个生命周期感知组件在获取到ON_RESUME事件的时候获取camera的例子。

KOTLINJAVA

public class CameraComponent implements LifecycleObserver {

    ...

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

    ...
}

 

The code above initializes the camera once the LifecycleObserver receives the ON_RESUME event. In multi-window mode, however, your activity may be fully visible even when it is in the Paused state. For example, when the user is in multi-window mode and taps the other window that does not contain your activity, your activity will move to the Paused state. If you want the camera active only when the app is Resumed (visible and active in the foreground), then initialize the camera after the ON_RESUME event demonstrated above. If you want to keep the camera active while the activity is Paused but visible (e.g. in multi-window mode) then you should instead initialize the camera after the ON_START event. Note, however, that having the camera active while your activity is Paused may deny access to the camera to another Resumed app in multi-window mode. Sometimes it may be necessary to keep the camera active while your activity is Paused, but it may actually degrade the overall user experience if you do. Think carefully about where in the lifecycle it is more appropriate to take control of shared system resources in the context of multi-window. To learn more about supporting multi-window mode, see Multi-Window Support.

上面的代码在LifecycleObserver获取到ON_RESUME事件的时候初始化了camera。在多窗口的模式下,你的actiivty可能会处于Paused状态但却仍然可见的状态下。比如说,当用户在多窗口的模式点击了其他的不包含你的activity的window,你的activity会变成paused状态。如果你希望camera只在app处于resumed状态下才处于活跃状态,那么你应该如上面的代码那样在接收到ON_RESUME事件后初始化camera。如果你想在actiivty处于paused状态,但仍然可见的状态下(多窗口模式下),camera仍然是处于活跃状态的,那么你就应该在接收到ON_START事件之后,初始化camera。但要注意的是,当activity处于paused状态的时候仍然持有camera可能会造成其他处于resumed状态下的app无法获取camera(多窗口模式下)。也许有时候你必须在activity处于paused状态的时候也要持有camera,但这会降低用户整体的体验。因此,关于在actiivity的哪一个生命周期之中获取共享资源的问题(多窗口模式下),应该更加小心地想清楚。如果需要学习更多关于多窗口模式的相关信息,查看 Multi-Window Support。

Regardless of which build-up event you choose to perform an initialization operation in, make sure to use the corresponding lifecycle event to release the resource. If you initialize something after the ON_START event, release or terminate it after the ON_STOP event. If you initialize after the ON_RESUME event, release after the ON_PAUSE event.

不管你选择在哪一个生命周期中初始化相应的资源,都一定要相应的生命周期中释放相应的资源。如果你在ON_START事件之后初始化了一些资源,那么你应该在ON_STOP事件之后,释放或终止相应的资源。

Note, the code snippet above places camera initialization code in a lifecycle aware component. You can instead put this code directly into the activity lifecycle callbacks such as onStart() and onStop() but this isn't recommended. Adding this logic into an independent, lifecycle-aware component allows you to reuse the component across multiple activities without having to duplicate code. See Handling Lifecycles with Lifecycle-Aware Components to learn how to create a lifecycle-aware component.

记住,上述的代码时在生命周期感知组件中初始化camera的。你也可以直接在activity的生命周期中初始化,但这是不提倡的。在一个独立的,生命周期感知的组件中添加这个逻辑会允许你在多个actiivty中复用这个组件,而不需要重复代码。See Handling Lifecycles with Lifecycle-Aware Components如何创建一个生命周期感知组件。

onPause()

The system calls this method as the first indication that the user is leaving your activity (though it does not always mean the activity is being destroyed); it indicates that the activity is no longer in the foreground (though it may still be visible if the user is in multi-window mode). Use the onPause() method to pause or adjust operations that should not continue (or should continue in moderation) while the Activity is in the Paused state, and that you expect to resume shortly. There are several reasons why an activity may enter this state. For example:

系统会在用户打算离开activity的时候回调这个方法(尽管这不总是意味着这个activity将要被destroyed)。它暗示这个activity已经不再在前台存在了(尽管用户在多窗口模式下仍然可以看见这个activity)。你应该在actiivty处于paused状态下的时,调用onPause方法去暂停或者调整一些不应该再继续的操作。下面列出了几个activity会进入这个状态的几个理由:

1.一些事件打断了app的运行,就像在onResume()节讲的那样。这是最常见的例子。

2.在android7.0或者更多,多数的app都会在多窗口模式下运行,但是任何时候都只会有一个app获取到用户的焦点,这时候其他的app都会被pause。

3.一个新的,半透明的activity(比如说对话框)打开了。只要actiivity是部分可见,没有获得用户焦点的,同样会进入paused状态。

  • Some event interrupts app execution, as described in the onResume() section. This is the most common case.
  • In Android 7.0 (API level 24) or higher, multiple apps run in multi-window mode. Because only one of the apps (windows) has focus at any time, the system pauses all of the other apps.
  • A new, semi-transparent activity (such as a dialog) opens. As long as the activity is still partially visible but not in focus, it remains paused.

When the activity moves to the paused state, any lifecycle-aware component tied to the activity's lifecycle will receive the ON_PAUSE event. This is where the lifecycle components can stop any functionality that does not need to run while the component is not in the foreground, such as stopping a camera preview.

当activity进入了paused状态,任何绑定了。。。你应该在这个状态停止一些不需要运行在非前台的操作。

You can also use the onPause() method to release system resources, handles to sensors (like GPS), or any resources that may affect battery life while your activity is paused and the user does not need them. However, as mentioned above in the onResume() section, a Paused activity may still be fully visible if in multi-window mode. As such, you should consider using onStop() instead of onPause() to fully release or adjust UI-related resources and operations to better support multi-window mode.

你同样可以使用onPause的方法去释放系统资源,处理传感器(比如GPS),或者其他任何当activity处于paused状态情况下,用户不需要的,有可能影响电池寿命的资源。

The following example of a LifecycleObserver reacting to the ON_PAUSE event is the counterpart to the ON_RESUME event example above, releasing the camera that was initialized after the ON_RESUME event was received:

KOTLINJAVA

public class JavaCameraComponent implements LifecycleObserver {

    ...

    @OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)
    public void releaseCamera() {
        if (camera != null) {
            camera.release();
            camera = null;
        }
    }

    ...
}

 

Note, the code snippet above places camera release code after the ON_PAUSE event is received by the LifecycleObserver. As previously mentioned, see Handling Lifecycles with Lifecycle-Aware Components to learn how to create a lifecycle-aware component.

onPause() execution is very brief, and does not necessarily afford enough time to perform save operations. For this reason, you should not use onPause() to save application or user data, make network calls, or execute database transactions; such work may not complete before the method completes. Instead, you should perform heavy-load shutdown operations during onStop(). For more information about suitable operations to perform during onStop(), see onStop(). For more information about saving data, see Saving and restoring activity state.

onPause()方法是非常简短的,你不应该在这里面进行保存用户数据之类的耗时操作,而应该在onStop方法中进行。

Completion of the onPause() method does not mean that the activity leaves the Paused state. Rather, the activity remains in this state until either the activity resumes or becomes completely invisible to the user. If the activity resumes, the system once again invokes the onResume() callback. If the activity returns from the Paused state to the Resumed state, the system keeps the Activity instance resident in memory, recalling that instance when the system invokes onResume(). In this scenario, you don’t need to re-initialize components that were created during any of the callback methods leading up to the Resumed state. If the activity becomes completely invisible, the system calls onStop(). The next section discusses the onStop() callback.

onPause方法的完成并不意味着actiivty已经离开了paused状态。相反,activity仍然会停留在这个状态,直到activity已经完全不可见了。如果activity恢复了,那么它会再次调用onResume方法。如果activity是从paused状态回到了resumed状态,系统将会保存activity的一个实例在内存中,当系统再次调用onResume方法的时候,重新使用这个实例。在这种情景之下,你不需要重新初始化那些你在任意的回调函数中初始化过的组件。如果activity变得完全不可见了,系统会调用onStop()。

onStop()

When your activity is no longer visible to the user, it has entered the Stopped state, and the system invokes the onStop() callback. This may occur, for example, when a newly launched activity covers the entire screen. The system may also call onStop() when the activity has finished running, and is about to be terminated.

当activity不再对用户可见时,它就进入了stopped的状态,系统会调用onStop()的回调函数。比如说,这将会发生在当一个新创建的activity占用了整个屏幕的时候。系统仍然会在activity结束运行,或者将要被终止的时候调用onStop方法。

When the activity moves to the stopped state, any lifecycle-aware component tied to the activity's lifecycle will receive the ON_STOP event. This is where the lifecycle components can stop any functionality that does not need to run while the component is not visible on the screen.

In the onStop() method, the app should release or adjust resources that are not needed while the app is not visible to the user. For example, your app might pause animations or switch from fine-grained to coarse-grained location updates. Using onStop() instead of onPause() ensures that UI-related work continues, even when the user is viewing your activity in multi-window mode.

在onStop方法中,你应该停止那些不需要再对用户可见的资源,比如,你的app也许会停止动画或从细粒度位置更新切换为粗粒度位置更新(。。。。)。

You should also use onStop() to perform relatively CPU-intensive(CPU密集型) shutdown operations. For example, if you can't find a more opportune time to save information to a database, you might do so during onStop(). The following example shows an implementation of onStop() that saves the contents of a draft note to persistent storage:

你还应该在onStop方法中来关闭相对比较占用cpu资源的资源。比如,如果你不能找到一个更加合适的时间段去保存信息到数据库,那么你就应该在onStop方法中进行这个操作。下面的这个例子展示了在onStop方法中保存一个草稿的笔记到一个持久的容器当中。

KOTLINJAVA

@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
    asyncQueryHandler.startUpdate (
            mToken,  // int token to correlate calls
            null,    // cookie, not used here
            uri,    // 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.
    );
}

 

Note, the code sample above uses SQLite directly. You should instead use Room, a persistence library that provides an abstraction layer over SQLite. To learn more about the benefits of using Room, and how to implement Room in your app, see the Room Persistence Library guide.

When your activity enters the Stopped state, the Activity object is kept resident in memory: It maintains all state and member information, but is not attached to the window manager. When the activity resumes, the activity recalls this information. You don’t need to re-initialize components that were created during any of the callback methods leading up to the Resumed state. The system also keeps track of the current state for each View object in the layout, so if the user entered text into an EditText widget, that content is retained so you don't need to save and restore it.

当activity进入stopped状态的时候,activity的实例仍然会在activity中保存。它保存了所有的状态和成员变量的信息,但是没有绑定到窗口管理器。当activity恢复的时候,系统会重新使用这些信息,你不需要重新初始化那些在别的回调函数中初始化过的参数。系统会跟踪每一个view在layout中的状态,因此当用户在EditText组件中输入text,这些text仍然会保存,而不需要进行保存和恢复的操作。

Note: Once your activity is stopped, the system might destroy the process that contains the activity if the system needs to recover memory. Even if the system destroys the process while the activity is stopped, the system still retains the state of the View objects (such as text in an EditText widget) in a Bundle (a blob of key-value pairs) and restores them if the user navigates back to the activity. For more information about restoring an activity to which a user returns, see Saving and restoring activity state.

From the Stopped state, the activity either comes back to interact with the user, or the activity is finished running and goes away. If the activity comes back, the system invokes onRestart(). If the Activity is finished running, the system calls onDestroy(). The next section explains the onDestroy() callback.

onDestroy()

onDestroy() is called before the activity is destroyed. The system invokes this callback either because:

  1. the activity is finishing (due to the user completely dismissing the activity or due to finish() being called on the activity), or
  2. the system is temporarily destroying the activity due to a configuration change (such as device rotation or multi-window mode)

When the activity moves to the destroyed state, any lifecycle-aware component tied to the activity's lifecycle will receive the ON_DESTROY event. This is where the lifecycle components can clean up anything it needs to before the Activity is destroyed.

Instead of putting logic in your Activity to determine why it is being destroyed you should use a ViewModel object to contain the relevant view data for your Activity. If the Activity is going to be recreated due to a configuration change the ViewModel does not have to do anything since it will be preserved and given to the next Activity instance. If the Activity is not going to be recreated then the ViewModel will have the onCleared() method called where it can clean up any data it needs to before being destroyed.

You can distinguish between these two scenarios with the isFinishing() method.

If the activity is finishing, onDestroy() is the final lifecycle callback the activity receives. If onDestroy() is called as the result of a configuration change, the system immediately creates a new activity instance and then calls onCreate() on that new instance in the new configuration.

The onDestroy() callback should release all resources that have not yet been released by earlier callbacks such as onStop().

Activity state and ejection from memory

The system kills processes when it needs to free up RAM; the likelihood of the system killing a given process depends on the state of the process at the time. Process state, in turn, depends on the state of the activity running in the process. Table 1 shows the correlation among process state, activity state, and likelihood of the system’s killing the process.

Likelihood of being killed Process state Activity state
Least Foreground (having or about to get focus) Created
Started
Resumed
More Background (lost focus) Paused
Most Background (not visible) Stopped
Empty Destroyed

Table 1. Relationship between process lifecycle and activity state

The system never kills an activity directly to free up memory. Instead, it kills the process in which the activity runs, destroying not only the activity but everything else running in the process, as well. To learn how to preserve and restore your activity's UI state when system-initiated process death occurs, see Saving and restoring activity state.

A user can also kill a process by using the Application Manager under Settings to kill the corresponding app.

For more information about processes in general, see Processes and Threads. For more information about how the lifecycle of a process is tied to the states of the activities in it, see the Process Lifecycle section of that page.

Saving and restoring transient UI state

A user expects an activity’s UI state to remain the same throughout a configuration change, such as rotation or switching into multi-window mode. However, the system destroys the activity by default when such a configuration change occurs, wiping away any UI state stored in the activity instance. Similarly, a user expects UI state to remain the same if they temporarily switch away from your app to a different app and then come back to your app later. However, the system may destroy your application’s process while the user is away and your activity is stopped.

When the activity is destroyed due to system constraints, you should preserve the user’s transient UI state using a combination of ViewModelonSaveInstanceState(), and/or local storage. To learn more about user expectations versus system behavior, and how to best preserve complex UI state data across system-initiated activity and process death, see Saving UI State.

This section outlines what instance state is and how to implement the onSaveInstance() method, which is a callback on the activity itself. If your UI data is simple and lightweight, such as a primitive data type or a simple object (like String), you can use onSaveInstanceState() alone to persist the UI state across both configuration changes and system-initiated process death. In most cases, though, you should use both ViewModel and onSaveInstanceState() (as outlined in Saving UI State) since onSaveInstanceState() incurs serialization/deserialization costs.

Instance state

There are a few scenarios in which your activity is destroyed due to normal app behavior, such as when the user presses the Back button or your activity signals its own destruction by calling the finish() method. When your activity is destroyed because the user presses Back or the activity finishes itself, both the system's and the user's concept of that Activity instance is gone forever. In these scenarios, the user's expectation matches the system's behavior and you do not have any extra work to do.

However, if the system destroys the activity due to system constraints (such as a configuration change or memory pressure), then although the actual Activity instance is gone, the system remembers that it existed. If the user attempts to navigate back to the activity, the system creates a new instance of that activity using a set of saved data that describes the state of the activity when it was destroyed.

The saved data that the system uses to restore the previous state is called the instance state and is a collection of key-value pairs stored in a Bundle object. By default, the system uses the Bundle instance state to save information about each View object in your activity layout (such as the text value entered into an EditText widget). So, if your activity instance is destroyed and recreated, the state of the layout is restored to its previous state with no code required by you. However, your activity might have more state information that you'd like to restore, such as member variables that track the user's progress in the activity.

Note: In order for the Android system to restore the state of the views in your activity, each view must have a unique ID, supplied by the android:id attribute.

Bundle object isn't appropriate for preserving more than a trivial amount of data because it requires serialization on the main thread and consumes system-process memory. To preserve more than a very small amount of data, you should take a combined approach to preserving data, using persistent local storage, the onSaveInstanceState() method, and the ViewModel class, as outlined in Saving UI States.

Save simple, lightweight UI state using onSaveInstanceState()

As your activity begins to stop, the system calls the onSaveInstanceState() method so your activity can save state information to an instance state bundle. The default implementation of this method saves transient information about the state of the activity's view hierarchy, such as the text in an EditText widget or the scroll position of a ListView widget.

To save additional instance state information for your activity, you must override onSaveInstanceState() and add key-value pairs to the Bundle object that is saved in the event that your activity is destroyed unexpectedly. If you override onSaveInstanceState(), you must call the superclass implementation if you want the default implementation to save the state of the view hierarchy. For example:

KOTLINJAVA

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, currentScore);
    savedInstanceState.putInt(STATE_LEVEL, currentLevel);

    // Always call the superclass so it can save the view hierarchy state
    super.onSaveInstanceState(savedInstanceState);
}

 

Note: onSaveInstanceState() is not called when the user explicitly closes the activity or in other cases when finish()is called.

To save persistent data, such as user preferences or data for a database, you should take appropriate opportunities when your activity is in the foreground. If no such opportunity arises, you should save such data during the onStop() method.

Restore activity UI state using saved instance state

When your activity is recreated after it was previously destroyed, you can recover your saved instance state from the Bundle that the system passes to your activity. Both the onCreate() and onRestoreInstanceState() callback methods receive the same Bundle that contains the instance state information.

Because the onCreate() method is called whether the system is creating a new instance of your activity or recreating a previous one, you must check whether the state Bundle is null before you attempt to read it. If it is null, then the system is creating a new instance of the activity, instead of restoring a previous one that was destroyed.

For example, the following code snippet shows how you can restore some state data in onCreate():

KOTLINJAVA

@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
        currentScore = savedInstanceState.getInt(STATE_SCORE);
        currentLevel = savedInstanceState.getInt(STATE_LEVEL);
    } else {
        // Probably initialize members with default values for a new instance
    }
    // ...
}

 

Instead of restoring the state during onCreate() you may choose to implement onRestoreInstanceState(), which the system calls after the onStart() method. The system calls onRestoreInstanceState() only if there is a saved state to restore, so you do not need to check whether the Bundle is null:

KOTLINJAVA

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
    currentScore = savedInstanceState.getInt(STATE_SCORE);
    currentLevel = savedInstanceState.getInt(STATE_LEVEL);
}

 

Caution: Always call the superclass implementation of onRestoreInstanceState() so the default implementation can restore the state of the view hierarchy.

Navigating between activities

An app is likely to enter and exit an activity, perhaps many times, during the app’s lifetime. For example, the user may tap the device’s Back button, or the activity may need to launch a different activity. This section covers topics you need to know to implement successful activity transitions. These topics include starting an activity from another activity, saving activity state, and restoring activity state.

Starting one activity from another

An activity often needs to start another activity at some point. This need arises, for instance, when an app needs to move from the current screen to a new one.

Depending on whether your activity wants a result back from the new activity it’s about to start, you start the new activity using either the startActivity() or the startActivityForResult() method. In either case, you pass in an Intent object.

The Intent object specifies either the exact activity you want to start or describes the type of action you want to perform (and the system selects the appropriate activity for you, which can even be from a different application). An Intent object can also carry small amounts of data to be used by the activity that is started. For more information about the Intent class, see Intents and Intent Filters.

startActivity()

If the newly started activity does not need to return a result, the current activity can start it by calling the startActivity() method.

When working within your own application, you often need to simply launch a known activity. For example, the following code snippet shows how to launch an activity called SignInActivity.

KOTLINJAVA

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

 

Your application might also want to perform some action, such as send an email, text message, or status update, using data from your activity. In this case, your application might not have its own activities to perform such actions, so you can instead leverage the activities provided by other applications on the device, which can perform the actions for you. This is where intents are really valuable: You can create an intent that describes an action you want to perform and the system launches the appropriate activity from another application. If there are multiple activities that can handle the intent, then the user can select which one to use. For example, if you want to allow the user to send an email message, you can create the following intent:

KOTLINJAVA

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

 

The EXTRA_EMAIL extra added to the intent is a string array of email addresses to which the email should be sent. When an email application responds to this intent, it reads the string array provided in the extra and places them in the "to" field of the email composition form. In this situation, the email application's activity starts and when the user is done, your activity resumes.

startActivityForResult()

Sometimes you want to get a result back from an activity when it ends. For example, you may start an activity that lets the user pick a person in a list of contacts; when it ends, it returns the person that was selected. To do this, you call the startActivityForResult(Intent, int) method, where the integer parameter identifies the call. This identifier is meant to disambiguate between multiple calls to startActivityForResult(Intent, int) from the same activity. It's not global identifier and is not at risk of conflicting with other apps or activities.The result comes back through your onActivityResult(int, int, Intent) method.

When a child activity exits, it can call setResult(int) to return data to its parent. The child activity must always supply a result code, which can be the standard results RESULT_CANCELEDRESULT_OK, or any custom values starting at RESULT_FIRST_USER. In addition, the child activity can optionally return an Intent object containing any additional data it wants. The parent activity uses the onActivityResult(int, int, Intent) method, along with the integer identifier the parent activity originally supplied, to receive the information.

If a child activity fails for any reason, such as crashing, the parent activity receives a result with the code RESULT_CANCELED.

KOTLINJAVA

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));
             }
         }
     }
 }

 

Coordinating activities

When one activity starts another, they both experience lifecycle transitions. The first activity stops operating and enters the Paused or Stopped state, while the other activity is created. In case these activities share data saved to disc or elsewhere, it's important to understand that the first activity is not completely stopped before the second one is created. Rather, the process of starting the second one overlaps with the process of stopping the first one.

The order of lifecycle callbacks is well defined, particularly when the two activities are in the same process (app) and one is starting the other. Here's the order of operations that occur when Activity A starts Activity B:

  1. Activity A's onPause() method executes.
  2. Activity B's onCreate()onStart(), and onResume() methods execute in sequence. (Activity B now has user focus.)
  3. Then, if Activity A is no longer visible on screen, its onStop() method executes.

This predictable sequence of lifecycle callbacks allows you to manage the transition of information from one activity to another.

 

 

===============================================================================================

每日总结:

1.activity会在onStopped状态下仍然保存activity中的所有成员变量的状态,只是不再绑定了窗口管理器。

2.resumed状态是可交互状态,paused是activity失去用户焦点的状态。

started是可见状态,stopped是activity不再对用户可见的状态。

3.不应该在onResume和onPause方法中进行耗时操作。onStart和onStop貌似也是不应该进行耗时操作的。

4.在资源的获得和释放应该在相应的生命周期对中完成。

你可能感兴趣的:(android,developer)