Home >Java >javaTutorial >Android basics Activity life cycle

Android basics Activity life cycle

高洛峰
高洛峰Original
2017-01-07 15:34:551360browse

The same is true for learning technology. For technical documents or classic technical books, it is basically impossible to expect to completely master them after reading them once, so we need to often go back and read them carefully several times to understand the author's thoughts. Essence.

Recently, I reviewed the life cycle of Activity. I read relevant books and official documents, and gained a lot. I have greatly improved my previous understanding. I would like to share it with you here. one time.

Friends who are familiar with javaEE all know servlet technology. If we want to implement a servlet of our own, we need to inherit the corresponding base class and rewrite its methods. These methods will be called by the servlet container at the appropriate time. In fact, the Activity running mechanism in Android is somewhat similar to servlet. The Android system is equivalent to a servlet container, and Activity is equivalent to a servlet. Our Activity is in this container, and all processes such as instance creation, initialization, and destruction of instances are performed by the container. Called, this is the so-called "Don't call me, I'll call you." mechanism.

Let’s take a look at this classic life cycle flow chart:

Android basics Activity life cycle

I believe many friends have already seen this flow chart, and it is basically Now that we understand several processes in the Activity life cycle, let’s talk about these processes.

1. Start Activity: The system will first call the onCreate method, then call the onStart method, and finally call onResume, and the Activity will enter the running state.

2. The current Activity is overwritten by other activities or the screen is locked: the system will call the onPause method to suspend the execution of the current Activity.

3. The current Activity returns to the foreground or unlocks the screen from the covered state: the system will call the onResume method and enter the running state again.

4. The current Activity switches to the new Activity interface or presses the Home button to return to the home screen, and retreats to the background: the system will first call the onPause method, and then call the onStop method to enter a stagnant state.

5. The user returns to this Activity: the system will first call the onRestart method, then call the onStart method, and finally call the onResume method to enter the running state again.

6. The current Activity is overwritten or invisible in the background, that is, in steps 2 and 4, the system has insufficient memory and kills the current Activity. Then the user returns to the current Activity: call the onCreate method and onStart again. Method, onResume method, enter the running state.

7. The user exits the current Activity: The system first calls the onPause method, then calls the onStop method, and finally calls the onDestory method to end the current Activity.

But knowing these is not enough. We must try it ourselves to deeply understand and understand it.

Below we will use examples to demonstrate the details of several processes in the life cycle.

We create a new project called lifecycle and create an Activity called LifeCycleActivity, as follows:

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

Everyone noticed that in addition to several common methods, we also added onWindowFocusChanged, onSaveInstanceState, onRestoreInstanceState methods:

1.onWindowFocusChanged method: called when the Activity window gains or loses focus, such as when it is first presented to the user when it is created; the current Activity is overwritten by other Activity; the current Activity goes to other Activity or Press the Home button to return to the home screen and retreat to the background; the user exits the current Activity. OnWindowFocusChanged will be called in the above situations, and when the Activity is created, it is called after onResume. When the Activity is overwritten or retreated to the background or the current Activity exits, it is called after onPause, as shown in the figure:

Android basics Activity life cycle

This method is still very useful in certain situations. For example, when you want to get the size of a specific view component when the program starts, you may not be able to get it in onCreate because the window The Window object has not been created yet, so we need to get it in onWindowFocusChanged at this time; if you have read the article I wrote about Frame Animation for Android animation, you will know that the reason why trying to load the frame animation in onCreate failed is because The window object was not initialized, so in the end I put the code for loading animation in onWindowFocusChanged, and the problem was solved. However, you may be wondering why I commented it out in the code, because every operation of the current Activity has its execution log. I was worried that this would affect the clarity of the entire process, so I commented it out. Everyone just needs to understand the occasions where it is applied and the order of execution.

2.onSaveInstanceState:(1)在Activity被覆盖或退居后台之后,系统资源不足将其杀死,此方法会被调用;(2)在用户改变屏幕方向时,此方法会被调用;(3)在当前Activity跳转到其他Activity或者按Home键回到主屏,自身退居后台时,此方法会被调用。第一种情况我们无法保证什么时候发生,系统根据资源紧张程度去调度;第二种是屏幕翻转方向时,系统先销毁当前的Activity,然后再重建一个新的,调用此方法时,我们可以保存一些临时数据;第三种情况系统调用此方法是为了保存当前窗口各个View组件的状态。onSaveInstanceState的调用顺序是在onPause之前。

3.onRestoreInstanceState:(1)在Activity被覆盖或退居后台之后,系统资源不足将其杀死,然后用户又回到了此Activity,此方法会被调用;(2)在用户改变屏幕方向时,重建的过程中,此方法会被调用。我们可以重写此方法,以便可以恢复一些临时数据。onRestoreInstanceState的调用顺序是在onStart之后。

以上着重介绍了三个相对陌生方法之后,下面我们就来操作一下这个Activity,看看它的生命周期到底是个什么样的过程:

1.启动Activity:

在系统调用了onCreate和onStart之后,调用了onResume,自此,Activity进入了运行状态。

2.跳转到其他Activity,或按下Home键回到主屏:

我们看到,此时onSaveInstanceState方法在onPause之前被调用了,并且注意,退居后台时,onPause后onStop相继被调用。

3.从后台回到前台:

当从后台会到前台时,系统先调用onRestart方法,然后调用onStart方法,最后调用onResume方法,Activity又进入了运行状态。

4.修改TargetActivity在AndroidManifest.xml中的配置,将android:theme属性设置为@android:style/Theme.Dialog,然后再点击LifeCycleActivity中的按钮,跳转行为就变为了TargetActivity覆盖到LifeCycleActivity之上了,此时调用的方法为:

注意还有一种情况就是,我们点击按钮,只是按下锁屏键,执行的效果也是如上。

我们注意到,此时LifeCycleActivity的OnPause方法被调用,并没有调用onStop方法,因为此时的LifeCycleActivity没有退居后台,只是被覆盖或被锁屏;onSaveInstanceState会在onPause之前被调用。

5.按回退键使LifeCycleActivity从被覆盖回到前面,或者按解锁键解锁屏幕:

此时只有onResume方法被调用,直接再次进入运行状态。

6.退出:

最后onDestory方法被调用,标志着LifeCycleActivity的终结。

大家似乎注意到,在所有的过程中,并没有onRestoreInstanceState的出现,这个并不奇怪,因为之前我们就说过,onRestoreInstanceState只有在杀死不在前台的Activity之后用户回到此Activity,或者用户改变屏幕方向的这两个重建过程中被调用。我们要演示第一种情况比较困难,我们可以结合第二种情况演示一下具体过程。顺便也向大家讲解一下屏幕方向改变的应对策略。

首先介绍一下关于Activity屏幕方向的相关知识。

我们可以为一个Activity指定一个特定的方向,指定之后即使转动屏幕方向,显示方向也不会跟着改变:

1.指定为竖屏:在AndroidManifest.xml中对指定的Activity设置android:screenOrientation="portrait",或者在onCreate方法中指定:

setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);//竖屏

2.指定为横屏:在AndroidManifest.xml中对指定的Activity设置android:screenOrientation="landscape",或者在onCreate方法中指定:

setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);//横屏

为应用中的Activity设置特定的方向是经常用到的办法,可以为我们省去不少不必要的麻烦。不过,我们今天讲的是屏幕方向改变时的生命周期,所以我们并不采用固定屏幕方向这种办法。


下面我们就结合实例讲解一下屏幕转换的生命周期,我们新建一个Activity命名为OrientationActivity,如下:

package com.scott.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;
     
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.orientation_portrait);
        Log.i(TAG, "onCreate called.");
    }
     
    @Override
    protected void onStart() {
        super.onStart();
        Log.i(TAG, "onStart called.");
    }
     
    @Override
    protected void onRestart() {
        super.onRestart();
        Log.i(TAG, "onRestart called.");
    }
     
    @Override
    protected void onResume() {
        super.onResume();
        Log.i(TAG, "onResume called.");
    }
     
    @Override
    protected void onPause() {
        super.onPause();
        Log.i(TAG, "onPause called.");
    }
     
    @Override
    protected void onStop() {
        super.onStop();
        Log.i(TAG, "onStop called.");
    }
     
    @Override
    protected void onDestroy() {
        super.onDestroy();
        Log.i(TAG, "onDestory called.");
    }
 
    @Override
    protected void onSaveInstanceState(Bundle outState) {
        outState.putInt("param", param);
        Log.i(TAG, "onSaveInstanceState called. put param: " + param);
        super.onSaveInstanceState(outState);
    }
     
    @Override
    protected void onRestoreInstanceState(Bundle savedInstanceState) {
        param = savedInstanceState.getInt("param");
        Log.i(TAG, "onRestoreInstanceState called. get param: " + param);
        super.onRestoreInstanceState(savedInstanceState);
    }
     
    //当指定了android:configChanges="orientation"后,方向改变时onConfigurationChanged被调用
    @Override
    public void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);
        Log.i(TAG, "onConfigurationChanged called.");
        switch (newConfig.orientation) {
        case Configuration.ORIENTATION_PORTRAIT:
            setContentView(R.layout.orientation_portrait);
            break;
        case Configuration.ORIENTATION_LANDSCAPE:
            setContentView(R.layout.orientation_landscape);
            break;
        }
    }
}

首先我们需要进入“Settings->Display”中,将“Auto-rotate Screen”一项选中,表明可以自动根据方向旋转屏幕,然后我们就可以测试流程了,当我们旋转屏幕时,我们发现系统会先将当前Activity销毁,然后重建一个新的:

Android basics Activity life cycle

The system first calls the onSaveInstanceState method. We save a temporary parameter into the Bundle object, and then we successfully retrieve this parameter after the Activity is rebuilt.

In order to avoid this destruction and reconstruction process, we need to configure android:configChanges="orientation" for the corresponding to OrientationActivity in AndroidMainfest.xml, and then we test it again. I tried four The rotation is printed as follows:

Android basics Activity life cycle

It can be seen that every time the direction of rotation is rotated, only the onConfigurationChanged method is called, and there is no process of destruction and reconstruction.

The following are some points to note:

1. If is configured with the android:screenOrientation attribute, it will invalidate android:configChanges="orientation".

2. There is a big difference between the simulator and the real machine: if the android:configChanges attribute is not configured in the simulator or the configuration value is orientation, switch to the horizontal screen and execute a destroy->rebuild, switch to the vertical screen and execute twice. Real machines are all one time. If you configure android:configChanges="orientation|keyboardHidden" (if it is Android 4.0, it is "orientation|keyboardHidden|screenSize") in the simulator, onConfigurationChanged will be executed once when switching to vertical screen, and twice when switching to horizontal screen. Real machines are all one time.

The life cycle of Activity is inseparable from the robustness of the program. I hope friends can understand it carefully and apply it skillfully.


For more articles related to the Activity life cycle of Android basics, please pay attention to the PHP Chinese website!


Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn