Android 应用程序的 Activity 启动过程及其生命周期

本文深入解析了Android系统中Activity的生命周期及其启动机制,包括显式与隐式启动方式,以及各生命周期方法的执行流程。通过示例代码演示了Activity从创建到销毁的完整生命周期,帮助开发者理解如何有效管理资源和状态。

    在Android系统中,Activity和Service是应用程序的核心组件,它们组合在一起构成了一个完整的应用程序,应用程序框架层提供了一套完整的机制来协助应用程序启动这些Activity和Service,以及提供Binder机制帮助它们相互间进行通信。

    有两种操作会引发Activity的启动,一种用户点击应用程序图标时,Launcher会为我们启动应用程序的主Activity;应用程序的默认Activity启动起来后,它又可以在内部通过调用startActvity接口启动新的Activity,依此类推,每一个Activity都可以在内部启动新的Activity。通过这种连锁反应,按需启动Activity,从而完成应用程序的功能。

    Activity的启动方式有两种,一种是显式的,一种是隐式的,隐式启动可以使得Activity之间的藕合性更加松散,因此,这里只关注隐式启动Activity的方法。

    下面让我们首先通过一终流程图来看一下 Activity 的生命周期是怎样的,大家应该都很熟悉这张图吧

 

001555_lQ38_1391648.jpg

 

我来对这张流程做个简单的解释

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。

 

    接着通过一个实例来看一下 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. 程序启动后的显示界面

001556_YRiM_1391648.jpg

Log 打印的信息如下

001558_sUNx_1391648.jpg

 

2. 点击上图的 Start-subActivity 按钮后,界面跳转如下

001600_HWR2_1391648.jpg

Log 的追加打印的信息如下

001602_pPCS_1391648.jpg

 

3. 点击上图的 Finish-activity 按钮后,界面跳转如下

001603_0uS0_1391648.jpg

Log 追加打印的信息如下

001606_KqLM_1391648.jpg

 

    无论是通过点击应用程序图标来启动Activity,还是通过Activity内部调用startActivity接口来启动新的Activity,都要借助于应用程序框架层的ActivityManagerService服务进程。Service也是由ActivityManagerService进程来启动的。在Android应用程序框架层中,ActivityManagerService是一个非常重要的接口,它不但负责启动Activity和Service,还负责管理Activity和Service。

    Android应用程序框架层中的ActivityManagerService启动Activity的过程大致如下图所示:

003514_CwvA_1391648.jpg

     下面简要介绍一下启动的过程:

        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类,然后把它启动起来。

 

转载于:https://my.oschina.net/u/1391648/blog/282778

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值