[JIT_APP]Activity生命週期相關的7個方法

先發一張安卓官方文檔裏面的Activity生命週期圖解前端

下面在對這7個生命週期內相關的方法作一些簡單的介紹java

OnCreate()

當Activity被建立的時候,會自動運行該方法。該方法作一些初始化動做,該方法提供了一個Bundle類型的變量,這個變量中有這個Activity之前的狀態信息,前提是之前存過這些信息。這個方法執行完以後執行的是OnStart()方法;若在OnCreate()方法中調用finish()方法,OnCreate()方法執行完以後直接調用OnDestroy()方法。android

通常在裏面設置所使用的佈局文件,而且進行一些靜態的的操做。app

 

OnRestart()

把一個Activity從OnStop狀態喚醒時,會調用OnRestart()方法,這個方法優先於再次運行的OnStart(),執行完OnRestart()以後再執行OnStart()。若在OnRestart()方法中加入finish()方法,則仍是會繼續執行OnStart()及後面的狀態方法直到OnDestroy()運行完。ide

 

OnStart()

當一個Activity對用戶可見時會調用OnStart(),當Activity在前臺運行時(得到輸入焦點),會調用OnResume();佈局

當Activity還沒在前臺運行就被隱藏了會運行OnStop(),好比在OnStart()方法中用finish()方法的話,OnStart()以後就會直接運行OnStop()→OnDestroy()。測試

 

OnResume()

當Activity開始與用戶交互時(得到用戶焦點),會調用OnResume(),而且爲了用戶操做,此時該Activity位於Activity棧的頂部。通過某些操做後該方法執行完以後執行的是OnPause()。動畫

 

OnPause()

當一個Activity運行到OnResume()方法以後,不論是這個Activity要銷燬仍是要暫停或者中止,都會調用該方法。這個方法以後多是OnResume()或者OnStop()。this

應用程序啓動了另一個Activity時候,第一個Activity也會調用OnPause()。例如:在操做時,來了一個電話,會調用前一個Activity的OnPause()方法,作一些保存工做,便於恢復。3d

如果在這個Activity-A中打開一個不徹底覆蓋這個Activity-A的新的Activity-B,那麼Activity-A就會是OnPause()狀態,當Activity-B退出時,Activity-A就會執行OnResume()方法。如果須要退出Activity-A,那麼下一個就會執行OnStop()。OnPause()用於提交未保存發生變化了的持久化數據,及中止動畫及其餘比較消耗CPU的事件或者消耗電量的資源,這是爲了更好的運行新的Activity。

 

OnStop()

當這個Activity【徹底】看不見的時候,會調用OnStop()方法,由於另外一個Activity會調用OnResume()而且覆蓋這個Activity。如下三種狀況會使這個Activity調用OnStop()方法:

1.新的Activity被執行

2.一個已經存在的Activity被切換到最前端

3.這個Activity要被銷燬

若是經過用戶召回這個Activity,那麼會調用OnRestart()方法,若這個Activity要被銷燬,則調用OnDestroy()方法。

 

OnDestroy()

當Activity銷燬前會調用該方法,好比發生以下狀況:

1.Activity調用finish()方法來結束這個Activity

2.或者由於系統爲了節省空間而臨時銷燬這個Activity

這兩種狀況能夠經過isFinishing()方法判斷

 

Activity生命週期的幾個過程

1.啓動Activity:系統會先調用onCreate()方法,而後調用onStart()方法,最後調用onResume(),Activity進入運行狀態。

 

2.當前Activity被其餘Activity覆蓋或被鎖屏:系統會調用onPause()方法,暫停當前Activity的執行。

 

3.當前Activity由被覆蓋狀態回到前臺或解鎖屏:系統會調用onResume()方法,再次進入運行狀態。

 

4.當前Activity轉到新的Activity界面或按Home鍵回到主屏,自身退居後臺:系統會先調用onPause()方法,而後再調用onStop()方法,進入停滯狀態。

 

5.用戶後退回到此Activity:系統會先調用onRestart()方法,而後調用onStart()方法,最後調用onResume()方法,再次進入運行狀態。

 

6.當前Activity處於被覆蓋狀態或者後臺不可見狀態,即第2步或第4步,系統內存不足,殺死當前Activity,然後用戶退回當前Activity:再次調用onCreate()、onStart()、onResume(),進入運行狀態。

 

7.用戶退出當前Activity:系統會調用onPause()方法,而後調用onStop()方法,最後調用onDestory()方法,結束當前Activity。

 

可是知道這些還不夠,咱們必須親自試驗一下才能深入體會,融會貫通。

 

編寫程序測試

下面咱們就結合實例,來演示一下生命週期的幾個過程的詳細狀況。咱們新建一個名爲lifecycle的項目,建立一個名爲LifeCycleActivity的Activity,以下:

 

package com.pingge.lifecycle;

import java.lang.annotation.Target;

import android.os.Bundle;
import android.R.integer;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.util.Log;
import android.view.Menu;
import android.view.View;
import android.widget.Button;

public class LifeCycleActivity extends Activity
{
	private static final String TAG = "LifeCycleActivity";
	private Context context = this;
	private int param = 1;
	
	@Override
	protected void onCreate(Bundle savedInstanceState)
	{
		// TODO Activity建立時被調用
		super.onCreate(savedInstanceState);
		Log.i(TAG, "onCreate() called");
		
		setContentView(R.layout.activity_life_cycle);
		
		Button btn = (Button)findViewById(R.id.btn);
		btn.setOnClickListener(new View.OnClickListener()
		{
			
			@Override
			public void onClick(View v)
			{
				// TODO Auto-generated method stub
				Intent intent = new Intent(context, OrientationActivity.class);
				startActivity(intent);
			}
		});
	}

	@Override
	protected void onDestroy()
	{
		// TODO 退出當前Activity時被調用,調用以後Activity就結束了
		super.onDestroy();
		Log.i(TAG, "onDestory() called");
	}

	@Override
	protected void onPause()
	{
		// TODO Activity被覆蓋或者鎖屏時被調用
		super.onPause();
		Log.i(TAG, "onPause() called");
	}

	@Override
	protected void onRestart()
	{
		// TODO Activity從後臺從新回到前臺時被調用
		super.onRestart();
		Log.i(TAG, "onRestart() called");
	}

	@Override
	protected void onResume()
	{
		// TODO Activity建立或者從被覆蓋、後臺從新回到前臺時被調用
		super.onResume();
		Log.i(TAG, "onResume() called");
	}

	@Override
	protected void onStart()
	{
		// TODO Activity建立或者從後臺從新回到前臺時被調用
		super.onStart();
		Log.i(TAG, "onStart() called");
	}

	@Override
	protected void onStop()
	{
		// TODO 退出當前Activity或者跳轉到新的Activity時被調用
		super.onStop();
		Log.i(TAG, "onStop() called");
	}
	

	/* 
	 * Activity被系統殺死以後再從新建立時被調用
	 * 例如:屏幕方向改變時,Activity被銷燬再重建;
	 * 		當前Activity處於後臺,系統資源緊張將其殺死,用戶又啓動了該Activity
	 * 這兩種狀況下onRestoreInstanceState()都會被調用,在onStart()以後
	 * 
	 * @see android.app.Activity#onRestoreInstanceState(android.os.Bundle)
	 */
	@Override
	protected void onRestoreInstanceState(Bundle savedInstanceState)
	{
		// TODO Auto-generated method stub
		super.onRestoreInstanceState(savedInstanceState);
		param = savedInstanceState.getInt("param");
		Log.i(TAG, "onRestoreInstanceState() called : " + param);
	}

	/* 
	 * Activity被系統殺死時被調用
	 * 例如:屏幕方向改變時,Activity被銷燬再重建;
	 * 	 	當前Activity處於後臺,系統資源緊張將其殺死
	 * 另外,當跳轉到其餘Activity或者按HOME鍵回到主屏時該方法也會被調用
	 * 		系統是爲了保存當前View組件的狀態
	 * 在onPause()方法以後被調用
	 * 
	 * @see android.app.Activity#onSaveInstanceState(android.os.Bundle)
	 */
	@Override
	protected void onSaveInstanceState(Bundle outState)
	{
		// TODO Auto-generated method stub
		super.onSaveInstanceState(outState);
		outState.putInt("param", param + 1);
		Log.i(TAG, "onSaveInstanceState() called : " + param);
	}

	@Override
	public void onWindowFocusChanged(boolean hasFocus)
	{
		// TODO 當Activity窗口得到或失去焦點時被調用,在onResume()以後或onPause()以後
		super.onWindowFocusChanged(hasFocus);
		Log.i(TAG, "onWindowFocusChanged() called");
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu)
	{
		// Inflate the menu; this adds items to the action bar if it is present.
		getMenuInflater().inflate(R.menu.life_cycle, menu);
		return true;
	}

}

你們注意到,除了幾個常見的方法外,咱們還添加了

onWindowFocusChanged、onSaveInstanceState、onRestoreInstanceState這三個方法。

 

1. onWindowFocusChanged

    在Activity窗口得到或失去焦點時被調用,例如:建立時首次呈如今用戶面前;當前Activity被其餘Activity覆蓋;當前Activity轉到其餘Activity或按HOME鍵回到主屏,自身退居後臺;用戶退出當前Activity。以上幾種狀況都會調用onWindowFocusChanged,而且當Activity被建立時是在OnResume以後被調用,當Activity被覆蓋或者退居後臺或者當前Activity退出時,它是在onPause()以後被調用,以下圖所示:

這個方法在某種場合下仍是頗有用的,例如:程序啓動時想要獲取特定視圖組件的尺寸大小,在onCreate中可能沒法取到,由於窗口window對象還沒建立完成,這個時候咱們就須要在onWindowFocusChanged裏獲取。

 

2. onSaveInstanceState

     (1)在Activity被覆蓋或退居後臺以後,系統資源不足將其殺死,此方法會被調用。

     (2)在用戶改變屏幕方向時,此方法會被調用。

     (3)在當前Activity跳轉到其餘Activity或者按HOME鍵回到主屏,自身退居後臺時,此方法被調用。

第一種狀況咱們沒法保證何時發生,系統根據資源緊張程度去調度;

第二種是屏幕翻轉方向時,系統先銷燬當前的Activity,而後再重建一個新的,調用此方法時,咱們能夠保存一些臨時的數據;

第三種狀況系統調用此方法是爲了保存當前窗口各個View組件的狀態。onSaveInstanceState的調用順序是在onPause以後。

下圖是按Back鍵後的調用順序:

 

3. onRestoreInstanceState

    (1)在Activity被覆蓋或退居後臺以後,系統資源不足將其殺死,而後用戶又回到了此Activity,此方法會被調用。

    (2)在用戶改變屏幕方向時,重建的過程當中,此方法會被調用。

咱們能夠重寫此方法,以即可以恢復一些臨時數據。onRestoreInstanceState的調用順序是在onStart以後。

下圖是改變屏幕方向時的調用順序:

 

以上着重介紹了三個相對陌生的方法以後,下面咱們就來操做一下這個Activity,看看它的生命週期究竟是個什麼樣的過程。

 

操做Activity觀察結果

  • 啓動Activity

在系統調用了onCreate和onStart以後,調用了onResume,自此,Activity進入了運行狀態。

 

  • 跳轉到其餘Activity,或按下Home鍵回到主屏

咱們看到,此時onSaveInstanceState方法在onPause以後被調用了。

 

  • 從後臺回到前臺

從後臺回到前臺時,系統會先調用onRestart方法,而後調用onStart方法,最後調用onResume方法,Activity又進入了運行狀態。

 

  • 修改TargetActivity在AndroidManifest.xml中的配置,將android:theme屬性設置爲@android:style/Theme.Dialog,而後再點擊LifeCycleActivity中的按鈕,跳轉行爲就變爲了TargetActivity覆蓋到LifeCycleActivity之上了,此時調用的方法爲:

咱們注意到,此時LifeCycleActivity的onPause方法被調用,並無調用onStop方法,由於此時TargetActivity沒有徹底覆蓋掉LifeCycleActivity,LifeCycleActivity仍是有一部分處於可見狀態。

 

  • 按Back鍵使LifeCycleActivity從被不徹底覆蓋狀態回到前面

此時只有onResume方法被調用,直接再次進入運行狀態。

 

  • 退出

最後的onDestory方法被調用,標誌着LifeCycleActivity的終結。

 

 

你們彷佛注意到,在全部的過程當中,並無onRestoreInstanceState的出現,這個並不奇怪,由於以前咱們就說過,onRestoreInstanceState只有在

(1)殺死不在前臺的Activity以後用戶回到此Activity

(2)用戶改變屏幕方向的這兩個重建過程當中被調用。

 

咱們要演示第一種狀況比較困難,咱們能夠結合第二種狀況演示一下具體的過程。順便也向你們講解一下屏幕方向改變的應對策略。

咱們能夠爲一個Activity指定一個特定的方向,指定以後即便轉到屏幕方向,顯示方向也不會跟着改變:

 

  • 指定爲豎屏

在AndroidManifest.xml中對指定的Activity設置: android:screenOrientation="portrait"

或者在onCreate方法中指定:setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);

 

  • 指定爲橫屏

在AndroidManifest.xml中對指定的Activity設置: android:screenOrientation="landscape"

或者在onCreate方法中指定:setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);

 

爲應用中的Activity設置特定的方向是常常用到的辦法,能夠爲咱們省去很多沒必要要的麻煩。不過,咱們今天講的是屏幕方向改變時的生命週期,因此咱們並不採用固定屏幕方向這種辦法。

下面咱們就結合實例講解一下屏幕轉換的生命週期,咱們新建一個Activity命名爲OrientationActivity,以下:

 

package com.pingge.lifecycle;

import android.app.Activity;
import android.content.res.Configuration;
import android.os.Bundle;
import android.util.Log;

public class OrientationActivity extends Activity
{
	private static final String TAG = "OrientationActivity";
	private int param = 1;
	
	
	/* 
	 * 當指定了android:configChanges="orientation"後,
	 * 方向改變時,onConfigurationChanged被調用
	 * @see android.app.Activity#onConfigurationChanged(android.content.res.Configuration)
	 */
	@Override
	public void onConfigurationChanged(Configuration newConfig)
	{
		// TODO Auto-generated method stub
		super.onConfigurationChanged(newConfig);

		switch (newConfig.orientation)
		{
			case Configuration.ORIENTATION_PORTRAIT:
				Log.i(TAG, "onConfigurationChanged() called" + "PORTRAIT");
				break;
			case Configuration.ORIENTATION_LANDSCAPE:
				Log.i(TAG, "onConfigurationChanged() called" + "LANDSCAPE");
				break;
			default:
				Log.i(TAG, "onConfigurationChanged() called" + "DEFAULT");
				break;
		}
	}
	@Override
	protected void onCreate(Bundle savedInstanceState)
	{
		// TODO Auto-generated method stub
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_orientation);
		Log.i(TAG, "onCreate() called");
	}
	@Override
	protected void onDestroy()
	{
		// TODO Auto-generated method stub
		super.onDestroy();
		Log.i(TAG, "onDestory() called");
	}
	@Override
	protected void onPause()
	{
		// TODO Auto-generated method stub
		super.onPause();
		Log.i(TAG, "onPause() called");
	}
	@Override
	protected void onRestart()
	{
		// TODO Auto-generated method stub
		super.onRestart();
		Log.i(TAG, "onRestart() called");
	}
	@Override
	protected void onRestoreInstanceState(Bundle savedInstanceState)
	{
		// TODO Auto-generated method stub
		super.onRestoreInstanceState(savedInstanceState);
		param = savedInstanceState.getInt("param");
		Log.i(TAG, "onRestoreInstanceState() called : " + param);
	}
	@Override
	protected void onResume()
	{
		// TODO Auto-generated method stub
		super.onResume();
		Log.i(TAG, "onResume() called");
	}
	@Override
	protected void onSaveInstanceState(Bundle outState)
	{
		// TODO Auto-generated method stub
		super.onSaveInstanceState(outState);
		outState.putInt("param", param);
		Log.i(TAG, "onSaveInstanceState() called : " + param);
	}
	@Override
	protected void onStart()
	{
		// TODO Auto-generated method stub
		super.onStart();
		Log.i(TAG, "onStart() called");
	}
	@Override
	protected void onStop()
	{
		// TODO Auto-generated method stub
		super.onStop();
		Log.i(TAG, "onStop() called");
	}
	
	
}

首先咱們必須打開手機的"自動旋轉開關",代表能夠自動根據方向旋轉屏幕,而後咱們就能夠測試流程了,當咱們旋轉屏幕時,咱們發現系統會先將當前Activity銷燬,而後重建一個新的:

系統先是調用onPause方法暫停當前Activity,而後調用onSaveInstanceState方法,咱們保存了一個臨時參數到Bundle對象裏面,而後當Activity重建以後咱們又成功的取出了這個參數。

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.pingge.lifecycle"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="8"
        android:targetSdkVersion="18" />

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name="com.pingge.lifecycle.LifeCycleActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <activity
            android:name="com.pingge.lifecycle.TargetActivity" >
        </activity>
        <activity
            android:name="com.pingge.lifecycle.OrientationActivity"
            android:configChanges="orientation|screenSize" >
        </activity>
    </application>

</manifest>

  

爲了不這樣的銷燬重建的過程,咱們須要在AndroidManifest.xml中對OrientationActivity對應的<activity>配置android:configChanges="orientation|screenSize",而後咱們再測試一下,咱們試着作了四次旋轉,打印以下:

能夠看到,每次旋轉方向時,只有onConfigurationChanged方法被調用,沒有了銷燬重建的過程。

注意:

若是<activity>配置了android:screenOrientation屬性,則會使android:configChanges="orientation"失效。

 

總結:

當用戶本身退出程序的時候,建議在OnStop()方法中保存數據;

當用戶打開一個新的Activity的時候,建議經過OnSaveInstanceState()來保存數據;這裏在網上看到不少人說應該方法OnPause()裏保存,其實我以爲在打開新的一個Activity的時候,或者將程序至於後臺的時候,都會默認調用OnSaveInstanceState()方法,並且在這種暫停的狀態下,Android的內存管理機制也不太會殺死這種狀態的Activity。而用OnPause()保存的時候,如果下一個執行OnResume()方法的話,會影響速度,固然數據量小的話也感受不到。

相關文章
相關標籤/搜索