跟着Google学Android —— 3.1 管好Activity的生命周期

当我们在app的不同页面间穿梭翱翔的时候,app中的Activity也在他们各自的生命周期中转换着不同的状态。当用户执行进入或者是离开某个Activity的操作时,Android系统会调用一系列生命周期的回调函数进行处理,而我们也可以重写这些回调函数,让Activity在不同的状态下执行我们想要的操作。

生命周期回调方法

下图展示了一个Activity的生命周期以及回调方法。这张图看起来就像是一个梯形金字塔,每一步都对应着Activity的一种生命状态。

跟着Google学Android —— 3.1 管好Activity的生命周期_第1张图片

在这些状态中,只有如下三种状态是静态的,即可持续一段时间的,其他状态都是瞬态的:

Resumed:在这个状态下,Activity处于前台,用户可以与它交互(也可以称之为Running态,即运行态);

Paused:在这个状态下,Activity部分被其他Activity遮挡(其他处于前台的Activity是半透明的或者并没与充满整个屏幕),处在这个状态的Activity并不接收用户输入,也不执行任何代码;

Stopped:在这个状态下,Activity是完全被隐藏的,用户无法看到,这种状态可以认为Activity处于后台,这个Activity实例以及它的状态信息在这种状态下都被保存了下来,但是不能执行任何代码。

Created和Started这两个状态都是瞬间态的,系统会在到达这两个状态后很快就调用后面的生命周期回调方法,即系统在调用onCreate()之后紧跟着就会调用onStart(),然后再紧跟着调用onResume()。

Cteate Activity

当用户点击app图标后,系统会调用你声明为launcher(或是main)Activity对应的onCreate()方法。这个Activity也是你的app的UI主入口。这也是Android系统和其他编程模式不同的地方,它并不是通过调用main()函数来启动,而是在不同的生命周期状态时调用不同的生命周期回调方法。
我们可以在AndroidManifest.xml文件中通过intent-filter定义哪个Activity将作为launcher(一般在我们创建项目的时候Android Studio已经帮我们完成了这步):

    
        
        
    
需要注意的是,如果MAIN或者是LAUNCHER二者之一没有定义,则这个app的图标将不会显示在安卓系统中。

无论用户是在安卓系统中点击app图标开启一个Activity还是在app内部翱翔时跳转到新的Activity,系统都会通过调用onCreate()方法来创建对应的Activity实例。
onCreate()在一个Activity的生命周期中仅会调用一次,所以我们可以在这个方法中实现一些UI和成员变量的初始化动作,例如:
TextView mTextView; // Member variable for text view in the layout

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    // 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_message);
    
    // Make sure we're running on Honeycomb or higher to use ActionBar APIs
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
        // For the main activity, make sure the app icon in the action bar
        // does not behave as a button
        ActionBar actionBar = getActionBar();
        actionBar.setHomeButtonEnabled(false);
    }
}
技术上来说,在调用onStart()的时候Activity对用户就是可见的了。

总结下,创建Activity的三部曲:onCreate() -> onStart() -> onResume()。
跟着Google学Android —— 3.1 管好Activity的生命周期_第2张图片

Pause & Resume Activity

只要某个Activity是部分可见的,且并不处于焦点,则这个Activity就保持在Paused态。一旦完全不可见,则变为了stopped态。如果用户从Paused态回到这个Activity,则系统会调用onResume()方法,具体循环如下图:
跟着Google学Android —— 3.1 管好Activity的生命周期_第3张图片
虽然系统调用onPause()方法是因为你的Activity被部分遮挡,但更普遍的其实是用户就要离开你的app了,所以我们应该在这个状态下做些事情:
1) 停止动画或者是其他在执行的可能会消耗CPU的动作;
2) 提交未保存的修改,这个动作仅当可以确认用户希望这些数据在他们离开app后也可以得到的保存的时候(例如短信草稿);
3) 释放系统资源,例如broadcast receivers、对传感器(例如GPS)的操作以及其他可能在Paused时候消耗电量而用户又不需要的资源。
举个例子:
@Override
public void onPause() {
    super.onPause();  // Always call the superclass method first

    // Release the Camera because we don't need it when paused
    // and other activities might need to use it.
    if (mCamera != null) {
        mCamera.release();
        mCamera = null;
    }
}
在onPause()中我们应该尽量做些简单的操作,而避免做高CPU负荷的操作,例如写入数据库,因为这会减慢跳转到下一个Activity的速度(大负荷的操作我们可以在onStop()中执行)。
在Paused的时候,Activity的实例还是存储在内存中的,所以我们并不需要重新初始化各个部件。

当用户从Paused态恢复Activity的时候,系统就会调用onResume()。需要注意的是,每次Activity来到前台的时候系统都会调用这个方法,即使是app第一次启动。正是由于这样,我们需要在这个方法中实现对onPause()中释放的组件的重新初始化,以及对那些每次到达Resumed态都要发生的事件进行处理,举个例子:
@Override
public void onResume() {
    super.onResume();  // Always call the superclass method first

    // Get the Camera instance as the activity achieves full user focus
    if (mCamera == null) {
        initializeCamera(); // Local method to handle camera init
    }
}

Stop & Restart Activity

有几个关于stop和restart的关键场景:
1) 用户打开“最近使用的程序”窗口,从你的app跳转到另一个app,则你的app中目前在前台的Activity变为stopped态,如果用户通过点击你的app图标或者是“最近使用的程序”窗口再导航回你的app,则Activity会重新开始(restart);
2) 当用户在你的app中导航跳转到一个新的Activity时,当新的Activity被创建后当前的Activity就停止了,如果用户点击“返回”按钮,则这个Activity会重新开始;
3) 用户在使用app的时候在同一台手机上接到了一通电话。
从进入stop到restart再到resume的流程如下:
跟着Google学Android —— 3.1 管好Activity的生命周期_第4张图片
当Activity在stop之后,系统可能由于需要恢复系统内存而destroy Activity实例,极端情况下也可能不调用onDestroy()就直接将app的进程结束了。所以我们有必要在onStop()就释放可能漏内存的资源。
虽然我们在onPause()和onStop()中都会执行一些清理工作,但前面也提到了,onPause()中应尽量做一些简单的工作,而onStop()中可以做一些高负荷的工作。
举个例子:
@Override
protected void onStop() {
    super.onStop();  // Always call the superclass method first

    // 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());

    getContentResolver().update(
            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.
            );
}
在停止的时候,Activity实例会保存在内存中,所以在恢复的时候我们并不需要重新初始化。同时,系统也记录了布局中各个view的当前状态,所以如果用户在文本输入框中输入了文字,那么这些内容会被保存下来,所以并不需要我们去另外存储及还原它们。

onRestart()仅在Activity从stopped变为resumed态时会被调用,而onStart()在每次Activity变得可见的时候都会被调用(无论是restart的还是第一次创建),所以可以在onRestart()中执行一些特殊的恢复操作,仅在Activity之前是stopped,而不是destroyed的时候需要。
由于在onStop()的时候基本上清掉了所有资源,所以用onStart()来与onStop()作为配对是更好的,举个例子,当我们离开应用程序很久了之后,onStart()是一个很好的来验证app所需要的系统特性已经开启的地方:
@Override
protected void onStart() {
    super.onStart();  // Always call the superclass method first
    
    // The activity is either being restarted or started for the first time
    // so this is where we should make sure that GPS is enabled
    LocationManager locationManager = 
            (LocationManager) getSystemService(Context.LOCATION_SERVICE);
    boolean gpsEnabled = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
    
    if (!gpsEnabled) {
        // Create a dialog here that requests the user to enable GPS, and use an intent
        // with the android.provider.Settings.ACTION_LOCATION_SOURCE_SETTINGS action
        // to take the user to the Settings screen to enable GPS when they click "OK"
    }
}

@Override
protected void onRestart() {
    super.onRestart();  // Always call the superclass method first
    
    // Activity being restarted from stopped state    
}

Recreate Activity

当Activity是由于用户自己点击返回或者是Activity自己调用finish()而销毁的时候系统认为这个Activity实例永远地消失了,因为这些操作表明没有人再需要这个Activity了。但如果Activity是由于系统资源的限制被销毁的,那么系统会记住它的存在,当用户再回来的时候,系统会使用在销毁它的时候保存的数据来创建Activity实例。系统用来还原之前状态所用的保存数据叫做“Instance state”,是存储在Bundle对象中的键值对集合。
注意:每次当用户旋转屏幕的时候Activity都会被销毁并重建,因为旋转屏幕后屏幕的配置会改变,Activity有可能要加载其他的资源(如布局等)。
系统默认使用Bundle instance state来记录Activity布局中的每个view的信息,所以如果我们要保存额外的Activity信息,我们则需要重写onSaveInstanceState()这个回调方法,给Bundle对象添加键值对:
跟着Google学Android —— 3.1 管好Activity的生命周期_第5张图片
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);
}
当Activity要重建的时候,系统会将之前这个Bundle传到onCreate()和onRestoreInstanceState()这两个方法中。这两个方法的差别在于,onCreate()中并不会检查Bundle是否为null,而onRestoreInstanceState()仅当Bundle中有需要被还原的状态时才会被调用,所以并不需要检查是否为null,且这个方法是在onStart()后调用的。
两种方法还原数据举例:
@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
    }
    //...
}

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

Destroy Activity

onDestroy()是Activity生命周期的最后一个回调函数,这意味着Activity的生命已经走到了尽头。在这个方法中我们可以做一些清理工作,但其实大多数在onPause()和onStop()中都已经做掉了。需要注意的就是如果有service这种在后台跑的资源,可能会消耗CPU,所以在这里都要终结掉。
一般情况下系统会在onPause()和onStop()之后调用onDestroy(),但有一种例外:当你在onCreate()方法中调用finish(),这种情况下系统立即直接调用onDestroy(),不会经过onPause()和onStop()这种。
代码举例:
@Override
public void onDestroy() {
    super.onDestroy();  // Always call the superclass
    
    // Stop method tracing that the activity started during onCreate()
    android.os.Debug.stopMethodTracing();
}

谷歌官方的demo

你可能感兴趣的:(跟着Google学Android —— 3.1 管好Activity的生命周期)