美文网首页
378,android中Activity生命周期,函数调用顺序(

378,android中Activity生命周期,函数调用顺序(

作者: 枫叶1234 | 来源:发表于2020-12-25 11:18 被阅读0次
image.png 截屏2020-12-11 下午8.46.16.png 截屏2020-12-11 下午8.47.01.png

一个Activity从本质上讲拥有4种状态:

  • 运行:如果当前的activity在前台界面上时(堆栈顶端)。
  • 暂停:如果activity被另一个非全屏活动强占焦点并覆盖时(如弹窗dialog),它将会暂停。一个暂停的活动也是完全活跃的(它的所有的状态和成员信息将会保留,但activity本身将不会再依附于WindowsManager了),在内存极度缺乏的状态会被系统杀死。
  • 停止:如果activity完全被另一个全屏活动遮挡住时,它将会停止。该活动也仍保留全部的状态和成员信息,但将会被隐藏起来不再展示给用户,并且当内存在其他地方被需要时该活动就将会被系统杀死。
  • 重启:如果activity处于暂停或者停止状态,系统将会在内存中终止该活动无论是结束活动或者杀死进程。当它再一次展示给用户时,它必须是完全重启并且恢复到之前的状态。

状态转换

image.png

这张图从Activity的起点是从Activity running开始的

上图中我们可以看到Activity在生命周期状态进行转换的过程中,activity本身是在什么时候调用的onSaveInstanceState()方法与onRestoreInstanceState()方法来进行重要信息的存储与恢复的。因为在蜂巢版本之前onSaveInstanceState()方法只有在activity异常退出时才会调用,所以我们应该在onPause()方法中进行信息持久化存储的操作,在蜂巢之后的版本,生命周期就可以正常的调用onSaveInstanceState()方法来进行信息持久化存储的操作了。

部分实例列举

上面说了一堆Activity生命周期的定义,在实际应用中,我们更倾向于实践运用,所以我会列举部分实例。大家可以给我点个小星星

  • 打开activity关闭activity生命周期如下(启动与销毁)
// activity启动
05-24 11:16:44.124 16259-16259/com.perry.activitylifecycle E/TAG lifecycle:  ------>>> onCreate
05-24 11:16:44.125 16259-16259/com.perry.activitylifecycle E/TAG lifecycle:  ------>>> onStart
05-24 11:16:44.125 16259-16259/com.perry.activitylifecycle E/TAG lifecycle:  ------>>> onResume
// activity关闭
05-24 11:16:46.691 16259-16259/com.perry.activitylifecycle E/TAG lifecycle:  ------>>> onPause
05-24 11:16:47.038 16259-16259/com.perry.activitylifecycle E/TAG lifecycle:  ------>>> onStop
05-24 11:16:47.038 16259-16259/com.perry.activitylifecycle E/TAG lifecycle:  ------>>> onDestroy

可以看到正常的启动与关闭Activity不会调用onSaveInstanceState(Bundle)方法与onRestoreInstanceState(Bundle)方法,所以如果要离开该界面时,该界面的重要信息,我们要在onPause()或onStop()方法中进行存储。

  • 弹窗(dialog、popupwindow)
[空]

没错,你没看错。是空!因为dialog与popupwindow实际上是一个存在于这个activity上的控件,所以它并不会影响activity本身的生命周期!试想如果你每次弹窗你的activity都要走onPause方法的话,那你的一些存储持久化操作是不是会不停地无更新的存储呢?所以,不要被一些说法误导,如果你不知道,那么就去动手实践。

  • 打开Dialog样式的Activity(暂停状态)
// 在Manifest文件中首先设置dialog样式
<activity android:name=".TranslateActivity"
        android:theme="@style/Theme.AppCompat.Dialog">
</activity>
// 然后你懂得,我们来打开这个dialog样式的Activity
05-24 16:27:24.964 26913-26913/com.perry.activitylifecycle E/TAG lifecycle:  ------>>> onPause
05-24 16:27:25.206 26913-26913/com.perry.activitylifecycle E/TAG lifecycle:  ------>>> onSaveInstanceState
// 最后我们关闭这个Activity
05-24 16:27:28.227 26913-26913/com.perry.activitylifecycle E/TAG lifecycle:  ------>>> onResume
  • 屏幕旋转
05-24 11:24:47.377 16724-16724/com.perry.activitylifecycle E/TAG lifecycle:  ------>>> onPause
05-24 11:24:47.378 16724-16724/com.perry.activitylifecycle E/TAG lifecycle:  ------>>> onSaveInstanceState
05-24 11:24:47.378 16724-16724/com.perry.activitylifecycle E/TAG lifecycle:  ------>>> onStop
05-24 11:24:47.378 16724-16724/com.perry.activitylifecycle E/TAG lifecycle:  ------>>> onDestroy
05-24 11:24:47.451 16724-16724/com.perry.activitylifecycle E/TAG lifecycle:  ------>>> onCreate
05-24 11:24:47.454 16724-16724/com.perry.activitylifecycle E/TAG lifecycle:  ------>>> onStart
05-24 11:24:47.454 16724-16724/com.perry.activitylifecycle E/TAG lifecycle:  ------>>> onRestoreInstanceState
05-24 11:24:47.454 16724-16724/com.perry.activitylifecycle E/TAG lifecycle:  ------>>> onResume

此处的onSaveInstanceState(Bundle)方法与onRestoreInstanceState(Bundle)方法具体执行时机,当targetSdkVersion小于3时onSaveInstanceState是在onPause方法中调用的,而大于3时是在onStop方法中调用的。而onRestoreInstanceState是在onStart之后、onResume之前调用的。

  • 按Home键后再开启app(停止状态)
// 点击home键(菜单键)
05-24 11:50:25.097 17817-17817/com.perry.activitylifecycle E/TAG lifecycle:  ------>>> onPause
05-24 11:50:25.407 17817-17817/com.perry.activitylifecycle E/TAG lifecycle:  ------>>> onSaveInstanceState
05-24 11:50:25.407 17817-17817/com.perry.activitylifecycle E/TAG lifecycle:  ------>>> onStop
// 打开App
05-24 11:51:05.471 17817-17817/com.perry.activitylifecycle E/TAG lifecycle:  ------>>> onRestart
05-24 11:51:05.476 17817-17817/com.perry.activitylifecycle E/TAG lifecycle:  ------>>> onStart
05-24 11:51:05.476 17817-17817/com.perry.activitylifecycle E/TAG lifecycle:  ------>>> onResume

下面我们就结合实例,来演示一下生命周期的几个过程的详细情况。我们新建一个名为lifecycle的项目,创建一个名为LifeCycleActivity的Activity,如下:


package com.scott.lifecycle;
 
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
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;
    
    //Activity创建时被调用
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Log.i(TAG, "onCreate called.");
        
        setContentView(R.layout.lifecycle);
        
        Button btn = (Button) findViewById(R.id.btn);
        btn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent(context, TargetActivity.class);
                startActivity(intent);
            }
        });
    }
    
    //Activity创建或者从后台重新回到前台时被调用
    @Override
    protected void onStart() {
        super.onStart();
        Log.i(TAG, "onStart called.");
    }
    
    //Activity从后台重新回到前台时被调用
    @Override
    protected void onRestart() {
        super.onRestart();
        Log.i(TAG, "onRestart called.");
    }
    
    //Activity创建或者从被覆盖、后台重新回到前台时被调用
    @Override
    protected void onResume() {
        super.onResume();
        Log.i(TAG, "onResume called.");
    }
    
    //Activity窗口获得或失去焦点时被调用,在onResume之后或onPause之后
    /*@Override
    public void onWindowFocusChanged(boolean hasFocus) {
        super.onWindowFocusChanged(hasFocus);
        Log.i(TAG, "onWindowFocusChanged called.");
    }*/
    
    //Activity被覆盖到下面或者锁屏时被调用
    @Override
    protected void onPause() {
        super.onPause();
        Log.i(TAG, "onPause called.");
        //有可能在执行完onPause或onStop后,系统资源紧张将Activity杀死,所以有必要在此保存持久数据
    }
    
    //退出当前Activity或者跳转到新Activity时被调用
    @Override
    protected void onStop() {
        super.onStop();
        Log.i(TAG, "onStop called.");   
    }
    
    //退出当前Activity时被调用,调用之后Activity就结束了
    @Override
    protected void onDestroy() {
        super.onDestroy();
        Log.i(TAG, "onDestory called.");
    }
    
    /**
     * Activity被系统杀死时被调用.
     * 例如:屏幕方向改变时,Activity被销毁再重建;当前Activity处于后台,系统资源紧张将其杀死.
     * 另外,当跳转到其他Activity或者按Home键回到主屏时该方法也会被调用,系统是为了保存当前View组件的状态.
     * 在onPause之前被调用.
     */
    @Override
    protected void onSaveInstanceState(Bundle outState) {
        outState.putInt("param", param);
        Log.i(TAG, "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(TAG, "onRestoreInstanceState called. get param: " + param);
        super.onRestoreInstanceState(savedInstanceState);
    }
}

onCreate()方法中的参数Bundle savedInstanceState 的意义用法

Activity中有一个名称叫onCreate的方法。该方法是在Activity创建时被系统调用,是一个Activity生命周期的开始。可是有一点容易被忽视,就是onCreate方法的参数saveInsanceState。一般的程序开发中,很少用到这个参数。
onCreate方法的完整定义如下:
public void onCreate(Bundle saveInsanceState){
super.onCreate(saveInsanceState);
}

Bundle类型的数据与Map类型的数据相似,都是以key-value的形式存储数据的。
从字面上看saveInsanceState,是保存实例状态的。实际上,saveInsanceState也就是保存Activity的状态的。那么,saveInsanceState中的状态数据是从何处而来的呢?下面我们介绍Activity的另一个方法saveInsanceState。

onsaveInsanceState方法是用来保存Activity的状态的。当一个Activity在生命周期结束前,会调用该方法保存状态。

如下所示:
public void onSaveInsanceState(Bundle saveInsanceState){
super.onSaveInsanceState(saveInsanceState);
}

在实际应用中,当一个Activity结束前,如果需要保存状态,就在onsaveInsanceState中,将状态数据以key-value的形式放入到saveInsanceState中。这样,当一个Activity被创建时,就能从onCreate的参数saveInsanceState中获得状态数据。
状态这个参数在实现应用中有很大的用途,比如:一个游戏在退出前,保存一下当前游戏运行的状态,当下次开启时能接着上次的继续玩下去。再比如:电子书程序,当一本小说被阅读到第199页后退出了(不管是内存不足还是用户自动关闭程序),当下次打开时,读者可能已忘记了上次已阅读到第几页了,但是,读者想接着上次的读下去。如果采用saveInstallState参数,就很容易解决上述问题。

使用例子:


import android.app.Activity;

 import android.os.Bundle;

 import android.util.Log 

public class AndroidTest extends Activity {
     private static final String TAG = "MyNewLog"; 

    @Override

    public void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        // If an instance of this activity had previously stopped, we can get the original text it started with.

        if(null != savedInstanceState)

        {//因为Activity的生命周期原因 ,if 语句放着不一定能执行得到 应该结合实际情况

               int IntTest = savedInstanceState.getInt("IntTest");

               String StrTest = savedInstanceState.getString("StrTest");

         }

        setContentView(R.layout.main); 

    }

      @Override

    public void onSaveInstanceState(Bundle savedInstanceState) {

        // Save away the original text, so we still have it if the activity needs to be killed while paused.

      savedInstanceState.putInt("IntTest", 0);

      savedInstanceState.putString("StrTest", "savedInstanceState test");

      super.onSaveInstanceState(savedInstanceState);

       }

   @Override

    public void onRestoreInstanceState(Bundle savedInstanceState) {

      super.onRestoreInstanceState(savedInstanceState);

      int IntTest = savedInstanceState.getInt("IntTest");

      String StrTest = savedInstanceState.getString("StrTest");

      }

}

小结

文章中我们具体的了解了Activity的7大生命周期与4种本质状态,还有onSaveInstanceState(Bundle)方法与onRestoreInstanceState(Bundle)具体执行时机。便于我们更好的了解与利用Activity中的每一种生命周期方法。

相关文章

网友评论

      本文标题:378,android中Activity生命周期,函数调用顺序(

      本文链接:https://www.haomeiwen.com/subject/ujuwgktx.html