Android 應用程序的 Activity 啓動過程及其生命週期

    在Android系統中,Activity和Service是應用程序的核心組件,它們組合在一塊兒構成了一個完整的應用程序,應用程序框架層提供了一套完整的機制來協助應用程序啓動這些Activity和Service,以及提供Binder機制幫助它們相互間進行通訊。java

    有兩種操做會引起Activity的啓動,一種用戶點擊應用程序圖標時,Launcher會爲咱們啓動應用程序的主Activity;應用程序的默認Activity啓動起來後,它又能夠在內部經過調用startActvity接口啓動新的Activity,依此類推,每個Activity均可以在內部啓動新的Activity。經過這種連鎖反應,按需啓動Activity,從而完成應用程序的功能。android

    Activity的啓動方式有兩種,一種是顯式的,一種是隱式的,隱式啓動可使得Activity之間的藕合性更加鬆散,所以,這裏只關注隱式啓動Activity的方法。web

    下面讓咱們首先經過一終流程圖來看一下 Activity 的生命週期是怎樣的,你們應該都很熟悉這張圖吧app

 

 

我來對這張流程作個簡單的解釋框架

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

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

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

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

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

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

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

 

    接着經過一個實例來看一下 Activity 的整個生命週期,閒話少說,都在代碼裏了...

src\cn\lion\activitytest

  1. MainActivity.java

package cn.lion.activitytest;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
public class MainActivity extends Activity{
 private final static String LOG_TAG = "cn.lion.activitytest.MainActivity";
 private Button startButton = null;
 private int param = 1;
 
 //Activity建立時被調用
 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);
  
  startButton = (Button)findViewById(R.id.button_start);
  startButton.setOnClickListener(new View.OnClickListener(){
   @Override
   public void onClick(View v){
    Intent intent = new Intent("cn.lion.activitytest.subactivity");
    startActivity(intent);
   }
  });
  
  Log.i(LOG_TAG, "MainActivity onCreate() called");
 }
 
 //Activity建立或者從後臺從新回到前臺時被調用
 @Override
 protected void onStart(){
  super.onStart();
  Log.i(LOG_TAG, "MainActivity onStart() called");
 }
 
 //Activity從後臺從新回到前臺時被調用
 @Override
 protected void onRestart(){
  super.onRestart();
  Log.i(LOG_TAG, "MainActivity onRestart() called");
 }
 
 //Activity建立或者從被覆蓋、後臺從新回到前臺時被調用
 @Override
 protected void onResume(){
  super.onResume();
  Log.i(LOG_TAG, "MainActivity onResume() called");
 }
 
 //Activity被覆蓋到下面或者鎖屏時被調用  
    @Override  
 protected void onPause() {  
  super.onPause();  
  Log.i(LOG_TAG, "MainActivity onPause() called");  
  //有可能在執行完onPause或onStop後,系統資源緊張將Activity殺死,因此有必要在此保存持久數據  
 }
    
    //退出當前Activity或者跳轉到新Activity時被調用  
    @Override  
    protected void onStop() {  
     super.onStop();  
     Log.i(LOG_TAG, "MainActivity onStop() called");     
    }  
   
    //退出當前Activity時被調用,調用以後Activity就結束了  
    @Override  
    protected void onDestroy() {  
        super.onDestroy();  
        Log.i(LOG_TAG, "MainActivity onDestory() called");  
    }
    
    //Activity窗口得到或失去焦點時被調用,在onResume以後或onPause以後
    @Override
    public void onWindowFocusChanged(boolean hasFocus){
     super.onWindowFocusChanged(hasFocus);
     Log.i(LOG_TAG, "MainActivity onWindowFocusChanged() called");
    }
    
    /** 
     * Activity被系統殺死時被調用. 
     * 例如:屏幕方向改變時,Activity被銷燬再重建;當前Activity處於後臺,系統資源緊張將其殺死. 
     * 另外,當跳轉到其餘Activity或者按Home鍵回到主屏時該方法也會被調用,系統是爲了保存當前View組件的狀態. 
     * 在onPause以前被調用. 
     */  
    @Override  
    protected void onSaveInstanceState(Bundle outState) {  
     outState.putInt("param", param);  
        Log.i(LOG_TAG, " MainActivity onSaveInstanceState() called. put param: " + param);  
        super.onSaveInstanceState(outState);  
    } 
    
    /** 
     * Activity被系統殺死後再重建時被調用. 
     * 例如:屏幕方向改變時,Activity被銷燬再重建;當前Activity處於後臺,系統資源緊張將其殺死,用戶又啓動該Activity. 
     * 這兩種狀況下onRestoreInstanceState都會被調用,在onStart以後. 
     */  
    @Override  
    protected void onRestoreInstanceState(Bundle savedInstanceState) {  
     param = savedInstanceState.getInt("param");  
        Log.i(LOG_TAG, "MainActivity onRestoreInstanceState() called. get param: " + param);  
        super.onRestoreInstanceState(savedInstanceState);  
    }
}

   2. SubActivity.java

package cn.lion.activitytest;
import android.app.Activity;  
import android.os.Bundle;  
import android.util.Log;  
import android.view.View;    
import android.widget.Button;  
  
public class SubActivity extends Activity{  
    private final static String LOG_TAG = "cn.lion.activitytest.SubActivity";  
    private Button finishButton = null;  
    private int param = 2;
  
    @Override  
    public void onCreate(Bundle savedInstanceState) {  
        super.onCreate(savedInstanceState);  
        setContentView(R.layout.sub);  
  
        finishButton = (Button)findViewById(R.id.button_finish);  
        finishButton.setOnClickListener(new View.OnClickListener() {   
   @Override
   public void onClick(View v) {
             finish();
   }
  });  
          
        Log.i(LOG_TAG, "Sub Activity onCreate() called");  
    }  
    
 //Activity建立或者從後臺從新回到前臺時被調用
 @Override
 protected void onStart(){
  super.onStart();
  Log.i(LOG_TAG, "SubActivity onStart() called");
 }
 
 //Activity從後臺從新回到前臺時被調用
 @Override
 protected void onRestart(){
  super.onRestart();
  Log.i(LOG_TAG, "SubActivity onRestart() called");
 }
 
 //Activity建立或者從被覆蓋、後臺從新回到前臺時被調用
 @Override
 protected void onResume(){
  super.onResume();
  Log.i(LOG_TAG, "SubActivity onResume() called");
 }
 
 //Activity被覆蓋到下面或者鎖屏時被調用  
    @Override  
 protected void onPause() {  
  super.onPause();  
  Log.i(LOG_TAG, "SubActivity onPause() called");  
  //有可能在執行完onPause或onStop後,系統資源緊張將Activity殺死,因此有必要在此保存持久數據  
 }
    
    //退出當前Activity或者跳轉到新Activity時被調用  
    @Override  
    protected void onStop() {  
     super.onStop();  
     Log.i(LOG_TAG, "SubActivity onStop() called");     
    }  
   
    //退出當前Activity時被調用,調用以後Activity就結束了  
    @Override  
    protected void onDestroy() {  
        super.onDestroy();  
        Log.i(LOG_TAG, "SubActivity onDestory() called");  
    }
    
    //Activity窗口得到或失去焦點時被調用,在onResume以後或onPause以後
    @Override
    public void onWindowFocusChanged(boolean hasFocus){
     super.onWindowFocusChanged(hasFocus);
     Log.i(LOG_TAG, "SubActivity onWindowFocusChanged() called");
    }
    
    /** 
     * Activity被系統殺死時被調用. 
     * 例如:屏幕方向改變時,Activity被銷燬再重建;當前Activity處於後臺,系統資源緊張將其殺死. 
     * 另外,當跳轉到其餘Activity或者按Home鍵回到主屏時該方法也會被調用,系統是爲了保存當前View組件的狀態. 
     * 在onPause以前被調用. 
     */  
    @Override  
    protected void onSaveInstanceState(Bundle outState) {  
     outState.putInt("param", param);  
        Log.i(LOG_TAG, " SubActivity onSaveInstanceState() called. put param: " + param);  
        super.onSaveInstanceState(outState);  
    } 
    
    /** 
     * Activity被系統殺死後再重建時被調用. 
     * 例如:屏幕方向改變時,Activity被銷燬再重建;當前Activity處於後臺,系統資源緊張將其殺死,用戶又啓動該Activity. 
     * 這兩種狀況下onRestoreInstanceState都會被調用,在onStart以後. 
     */  
    @Override  
    protected void onRestoreInstanceState(Bundle savedInstanceState) {  
     param = savedInstanceState.getInt("param");  
        Log.i(LOG_TAG, "SubActivity onRestoreInstanceState() called. get param: " + param);  
        super.onRestoreInstanceState(savedInstanceState);  
    } 
    
}

res\values

strings.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string name="app_name">ActivityTest</string>
    <string name="action_settings">Settings</string>
    <string name="hello_world">Hello world!</string>
    <string name="sub_activity">SubActivity</string>
    <string name="start">Start-subActivity</string>
    <string name="finish">Finish-activity</string>
</resources>

res\layout

  1. activity_main.xml

<?xml version="1.0" encoding="utf-8"?>  
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
    android:orientation="vertical"  
    android:layout_width="fill_parent"  
    android:layout_height="fill_parent"   
    android:gravity="center">  
        <Button   
            android:id="@+id/button_start"  
            android:layout_width="wrap_content"  
            android:layout_height="wrap_content"  
            android:gravity="center"  
            android:text="@string/start" >  
        </Button>  
</LinearLayout>

 

  2. sub.xml

<?xml version="1.0" encoding="utf-8"?>  
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
    android:orientation="vertical"  
    android:layout_width="fill_parent"  
    android:layout_height="fill_parent"   
    android:gravity="center">  
        <Button   
            android:id="@+id/button_finish"  
            android:layout_width="wrap_content"  
            android:layout_height="wrap_content"  
            android:gravity="center"  
            android:text="@string/finish" >  
        </Button>  
</LinearLayout>

    接着一步一步來對這個簡單的應用進行操做,而後看一下它的執行結果(注意下面的 Log 信息是通過過濾器過濾的,我定義了一個只顯示 cn.lion.activitytest* 類型信息的過濾器...)

1. 程序啓動後的顯示界面

Log 打印的信息以下

 

2. 點擊上圖的 Start-subActivity 按鈕後,界面跳轉以下

Log 的追加打印的信息以下

 

3. 點擊上圖的 Finish-activity 按鈕後,界面跳轉以下

Log 追加打印的信息以下

 

    不管是經過點擊應用程序圖標來啓動Activity,仍是經過Activity內部調用startActivity接口來啓動新的Activity,都要藉助於應用程序框架層的ActivityManagerService服務進程。Service也是由ActivityManagerService進程來啓動的。在Android應用程序框架層中,ActivityManagerService是一個很是重要的接口,它不但負責啓動Activity和Service,還負責管理Activity和Service。

    Android應用程序框架層中的ActivityManagerService啓動Activity的過程大體以下圖所示:

     下面簡要介紹一下啓動的過程:

        Step 1. 不管是經過Launcher來啓動Activity,仍是經過Activity內部調用startActivity接口來啓動新的Activity,都經過Binder進程間通訊進入到ActivityManagerService進程中,而且調用ActivityManagerService.startActivity接口; 

        Step 2. ActivityManagerService調用ActivityStack.startActivityMayWait來作準備要啓動的Activity的相關信息;

        Step 3. ActivityStack通知ApplicationThread要進行Activity啓動調度了,這裏的ApplicationThread表明的是調用ActivityManagerService.startActivity接口的進程,對於經過點擊應用程序圖標的情景來講,這個進程就是Launcher了,而對於經過在Activity內部調用startActivity的情景來講,這個進程就是這個Activity所在的進程了;

        Step 4. ApplicationThread不執行真正的啓動操做,它經過調用ActivityManagerService.activityPaused接口進入到ActivityManagerService進程中,看看是否須要建立新的進程來啓動Activity;

        Step 5. 對於經過點擊應用程序圖標來啓動Activity的情景來講,ActivityManagerService在這一步中,會調用startProcessLocked來建立一個新的進程,而對於經過在Activity內部調用startActivity來啓動新的Activity來講,這一步是不須要執行的,由於新的Activity就在原來的Activity所在的進程中進行啓動;

        Step 6. ActivityManagerServic調用ApplicationThread.scheduleLaunchActivity接口,通知相應的進程執行啓動Activity的操做;

        Step 7. ApplicationThread把這個啓動Activity的操做轉發給ActivityThread,ActivityThread經過ClassLoader導入相應的Activity類,而後把它啓動起來。

相關文章
相關標籤/搜索