Heim  >  Artikel  >  Java  >  Android-Grundlagen: Aktivitätslebenszyklus

Android-Grundlagen: Aktivitätslebenszyklus

高洛峰
高洛峰Original
2017-01-07 15:34:551234Durchsuche

Das Gleiche gilt für technische Dokumente oder klassische technische Bücher, da es grundsätzlich unmöglich ist, sie vollständig zu verstehen, nachdem wir sie mehrmals gelesen haben, um die Gedanken des Autors zu verstehen . Essenz.

Ich habe kürzlich den Lebenszyklus von Activity durchgelesen und mein bisheriges Verständnis erheblich verbessert.

Freunde, die mit JavaEE vertraut sind, kennen alle die Servlet-Technologie. Wenn wir ein eigenes Servlet implementieren möchten, müssen wir die entsprechende Basisklasse erben und ihre Methoden neu schreiben zum richtigen Zeitpunkt. Tatsächlich ähnelt der Aktivitätsausführungsmechanismus in Android einem Servlet-Container, und die Aktivität entspricht einem Servlet, und alle Prozesse wie Instanzerstellung, Initialisierung usw. und die Zerstörung von Instanzen erfolgt durch den sogenannten „Don't call me, I’ll call you“-Mechanismus.

Werfen wir einen Blick auf dieses klassische Lebenszyklus-Flussdiagramm:

Android-Grundlagen: Aktivitätslebenszyklus

Ich glaube, viele Freunde haben dieses Flussdiagramm bereits gesehen, und im Grunde ist es so Wir verstehen mehrere Prozesse im Aktivitätslebenszyklus. Lassen Sie uns über diese Prozesse sprechen.

1. Starten Sie die Aktivität: Das System ruft zuerst die onCreate-Methode auf, ruft dann die onStart-Methode auf und ruft schließlich onResume auf, und die Aktivität wechselt in den laufenden Zustand.

2. Die aktuelle Aktivität wird durch andere Aktivitäten überschrieben oder der Bildschirm ist gesperrt: Das System ruft die onPause-Methode auf, um die Ausführung der aktuellen Aktivität anzuhalten.

3. Die aktuelle Aktivität kehrt in den Vordergrund zurück oder entsperrt den Bildschirm aus dem abgedeckten Zustand: Das System ruft die onResume-Methode auf und wechselt erneut in den laufenden Zustand.

4. Die aktuelle Aktivität wechselt zur neuen Aktivitätsoberfläche oder drückt die Home-Taste, um zum Startbildschirm zurückzukehren, und kehrt in den Hintergrund zurück: Das System ruft zuerst die Methode onPause auf und ruft dann die Methode onStop auf in einen stagnierenden Zustand geraten.

5. Der Benutzer kehrt zu dieser Aktivität zurück: Das System ruft zuerst die onRestart-Methode, dann die onStart-Methode und schließlich die onResume-Methode auf, um wieder in den laufenden Zustand zu gelangen.

6. Die aktuelle Aktivität wird im Hintergrund überschrieben oder ist unsichtbar, d. h. in den Schritten 2 und 4 verfügt das System nicht über genügend Speicher und bricht die aktuelle Aktivität ab onCreate-Methode und onStart-Methode, onResume-Methode, geben Sie den laufenden Status ein.

7. Der Benutzer verlässt die aktuelle Aktivität: Das System ruft zuerst die onPause-Methode auf, ruft dann die onStop-Methode auf und ruft schließlich die onDestory-Methode auf, um die aktuelle Aktivität zu beenden.

Aber das zu wissen reicht nicht aus. Wir müssen es selbst versuchen, um es tiefgreifend zu verstehen und zu verstehen.

Im Folgenden werden wir anhand von Beispielen die Details mehrerer Prozesse im Lebenszyklus demonstrieren.

Wir erstellen ein neues Projekt namens Lifecycle und eine Aktivität namens LifeCycleActivity wie folgt:

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

Jedem ist aufgefallen, dass wir zusätzlich zu mehreren gängigen Methoden auch onWindowFocusChanged, onSaveInstanceState und onRestoreInstanceState hinzugefügt haben Methoden:

1. onWindowFocusChanged-Methode: Wird aufgerufen, wenn das Aktivitätsfenster den Fokus erhält oder verliert, z. B. wenn es dem Benutzer zum ersten Mal angezeigt wird, wenn es von einer anderen Aktivität überschrieben wird Wechselt zu einer anderen Aktivität oder drückt die Home-Taste, um zum Startbildschirm zurückzukehren und in den Hintergrund zurückzukehren. Der Benutzer verlässt die aktuelle Aktivität. OnWindowFocusChanged wird in den oben genannten Situationen aufgerufen. Wenn die Aktivität erstellt wird, wird sie nach onResume aufgerufen. Wenn die Aktivität überschrieben oder in den Hintergrund verschoben wird oder die aktuelle Aktivität beendet wird, wird sie nach onPause aufgerufen, wie in der Abbildung gezeigt:

Android-Grundlagen: Aktivitätslebenszyklus

Diese Methode ist in bestimmten Situationen immer noch sehr nützlich. Wenn Sie beispielsweise beim Start des Programms die Größe einer bestimmten Ansichtskomponente ermitteln möchten, ist dies möglicherweise nicht möglich Um es in onCreate zu bekommen, weil das Fensterfensterobjekt noch nicht erstellt wurde, müssen wir es zu diesem Zeitpunkt in onWindowFocusChanged einfügen. Wenn Sie den Artikel gelesen haben, den ich über Frame Animation für Android-Animationen geschrieben habe, wissen Sie, warum Warum der Versuch, die Rahmenanimation in onCreate zu laden, fehlschlug, liegt daran, dass das Fensterobjekt nicht initialisiert wurde. Am Ende habe ich den Code zum Laden der Animation in onWindowFocusChanged eingefügt und das Problem wurde gelöst. Aber Sie fragen sich vielleicht, warum ich es im Code auskommentiert habe, denn jede Operation der aktuellen Aktivität hat ein eigenes Ausführungsprotokoll. Ich hatte Angst, dass dies die Klarheit des gesamten Prozesses beeinträchtigen würde, also habe ich es einfach auskommentiert die Gelegenheiten, bei denen es angewendet wird, und die Reihenfolge der Ausführung verstehen.

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-Grundlagen: Aktivitätslebenszyklus

Das System ruft zunächst die Methode onSaveInstanceState auf. Wir speichern einen temporären Parameter im Bundle-Objekt und rufen diesen Parameter dann erfolgreich ab, nachdem die Aktivität neu erstellt wurde.

Um einen solchen Zerstörungs- und Rekonstruktionsprozess zu vermeiden, müssen wir android:configChanges="orientation" für die entsprechend OrientationActivity in AndroidMainfest.xml konfigurieren und es dann erneut testen Ich habe vier ausprobiert Die Drehung wird wie folgt gedruckt:

Android-Grundlagen: Aktivitätslebenszyklus

Sie können sehen, dass bei jeder Drehung der Richtung nur die onConfigurationChanged-Methode aufgerufen wird und kein Zerstörungs- und Rekonstruktionsprozess stattfindet .

Die folgenden Punkte sind zu beachten:

1. Wenn mit dem Attribut android:screenOrientation konfiguriert ist, wird android:configChanges="orientation" ungültig.

2. Es gibt einen großen Unterschied zwischen dem Simulator und der realen Maschine: Wenn das Attribut android:configChanges nicht im Simulator konfiguriert ist oder der Konfigurationswert Orientierung ist, wechseln Sie zum horizontalen Bildschirm und führen Sie eine Zerstörung aus – > neu erstellen, zum vertikalen Bildschirm wechseln und zweimal ausführen. Echte Maschinen sind alle eins. Wenn android:configChanges="orientation|keyboardHidden" im Simulator konfiguriert ist (bei Android 4.0 ist es „orientation|keyboardHidden|screenSize“), wird onConfigurationChanged einmal ausgeführt, wenn auf den vertikalen Bildschirm umgeschaltet wird, und zweimal, wenn auf den horizontalen Bildschirm umgeschaltet wird Bildschirm. Echte Maschinen sind alle eins.

Der Lebenszyklus von Aktivität ist untrennbar mit der Robustheit des Programms verbunden. Ich hoffe, dass Freunde es sorgfältig verstehen und geschickt anwenden können.


Weitere Artikel zum Aktivitätslebenszyklus der Android-Grundlagen finden Sie auf der chinesischen PHP-Website!


Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn