如何实现Android生命周期的回调方法

175 阅读9分钟

如何实现Android生命周期的回调方法

Android生命周期帮助开发者了解当用户浏览应用程序时,活动会经历哪些状态。因此,我们可以在正确的时间进行适当的操作,避免崩溃和其他错误。

一个Android应用程序有一个生命周期。从用户打开和退出一个应用程序开始,它要经过各种阶段。

一个应用程序的状态可以帮助你管理用户何时打开一个活动、暂停、恢复、停止和销毁它。

回调方法管理这些状态。你可以覆盖这些方法来做一个特定的操作,给用户正确的输出。

比方说,你的应用程序在后台运行,你希望保存一些数据。在这种情况下,你必须了解活动的生命周期。这使你能够实现正确的回调来处理这种情况。

目标

在本教程中,我们将解释不同的Android应用程序生命周期回调状态。我们将讨论适用于安卓活动生命周期的所有状态。

我们将开发一个安卓应用,展示各种活动生命周期回调的发生地。这个应用程序将具有生命周期意识,以了解哪个回调正在被执行。

先决条件

要跟上进度,你应该有。

  • 安装了Android Studio。
  • 对Android应用开发有良好的理解。
  • 关于如何运行和使用Android Studio Logcat的预先知识。

不同活动生命周期的回调

现在让我们深入讨论不同的Android应用程序的生命周期,看看我们如何实现它们。

首先,确保Android Studio正在你的电脑上运行。

然后使用empty activity 模板创建一个新项目。在本教程中,我们将使用Java来构建一个Android应用程序。因此,请确保你选择Java作为你的首选编程语言。

Android application language

一个Android活动会经历六个主要的生命周期阶段或回调。它们是onCreate(),onStart(),onResume(),onPause(),onStop(), 和onDestroy() 。当一个活动进入一个新的状态时,系统会调用这些回调中的每一个。

注意,没有必要在你的Android应用程序中实现所有这些生命周期回调。作为一个开发者,你应该知道何时实现这些回调中的每一个,这取决于活动的复杂性。

下面是一个简化的图表,说明了用户是如何与活动生命周期进行交互的。

Activity lifecycle

图片来源

让我们讨论一下这个活动的生命周期,并在一个实际的Android应用程序中实现它们。

onCreate()

onCreate() 回调在所有的Android应用程序中是必须的。它是我们从主屏幕或意图启动一个活动时调用的第一个方法。换句话说,它是一个默认的回调,当你创建一个新的活动时,它会被自动创建。

它是开发者实现只应发生一次的活动逻辑的唯一方法,例如初始化一个ViewModel

Android Studio自动创建了一个名为MainActivity.java 文件的类。这个类包含一个onCreate() 回调。它在用户第一次打开应用程序时被调用。

当一个应用程序被安装在设备上时,它是在一个doesn't exist state 。这意味着活动是死的。

一旦用户打开应用程序,生命周期就开始了。该活动被带到了前台。在这种情况下,onCreate() 被立即调用以启动应用程序。它可能包含一些组件,如活动的用户界面。

下面是一个示例代码,显示了如何实现onCreate() 方法。我添加了一个Log 和一个Toast ,在本指南的后面我们将用它来读取活动的状态。

在你的MainActivity.java ,确保你的onCreate() 方法有下面的几行来打印一个ToastLog 消息。

private static final String TAG = "MainActivity";

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    Toast.makeText(this, "onCreate MainActivity", Toast.LENGTH_SHORT).show();
    Log.d(TAG, "onCreate MainActivity");
}

在这个步骤中,你的活动还不可见。它一直处于这种状态,直到onCreate() 函数完成,然后它迅速地进入下一个状态。

onStart()

当一个应用程序被启动时,系统将调用一个onStart() 方法。这个回调被调用以使活动对用户可见。

下面是onStart() 的实现方式。

@Override
protected void onStart() {

    Toast.makeText(this, "onStart MainActivity", Toast.LENGTH_SHORT).show();
        Log.d(TAG, "onStart MainActivity");

    super.onStart();
}

onStart() 在一个应用程序的生命周期中可以被调用几次。例如,当用户打开另一个活动,然后导航回上一个活动时,这个方法可以被调用。

在活动的生命周期中,onStop() 函数被调用。这意味着一些资源被释放。onStart() 方法可以被调用来初始化这些资源。

onResume()

一旦onStart() 被调用,onResume() 被立即调用。与该活动相关的每个组件都被带到前台状态。该活动现在被认为是交互式的。

@Override
protected void onResume() {

    Toast.makeText(this, "onResume MainActivity", Toast.LENGTH_SHORT).show();
    Log.d(TAG, "onResume MainActivity");
    super.onResume();

}

在这一点上,该活动保持在前台状态,除非应用程序发生了什么事情。这可能包括来自其他应用程序的过度(多窗口模式的应用程序)交互,如电话或当用户导航到另一个活动时。

onPause()

onPause() 在用户切换到另一个活动或多窗口模式的应用程序时被调用。此时,该活动已经失去了焦点并在后台运行。

这个回调将暂停该活动并释放该活动所消耗的一些资源。所有未被要求的操作都被暂停了。

@Override
protected void onPause() {

    Toast.makeText(this, "onPause MainActivity", Toast.LENGTH_SHORT).show();
    Log.d(TAG, "onPause MainActivity");

    super.onPause();
}

onPause() 被调用时,你可能会从内存中释放一些资源。然而,请确保你在onResume() 回调期间再次初始化它们。

onPause() 是一个简短的回调,允许过渡到其他活动。所以,在这个阶段不应该执行密集的计算。这可能会延迟应用程序向其他活动的过渡,从而导致糟糕的用户体验。

onStop()

在这一点上,大部分的活动进程已经被停止。然而,该活动仍在后台运行。

这个生命周期通常发生在onPause() 方法执行后,由于用户切换到其他活动或按下Home键。

在这种情况下,它被用来释放沉重的资源,并在活动不可见时停止不需要的密集操作。

由于onPause() 是短暂的,onStop() 可以用来将数据保存到其他渠道,如数据库。

@Override
protected void onStop() {

    Toast.makeText(this, "onStop MainActivity", Toast.LENGTH_SHORT).show();
    Log.d(TAG, "onStop MainActivity");

    super.onStop();
}

注意:在这个时候,这个活动还没有被销毁。活动实例被保存在一个回栈中。这意味着所有陈述仍然是活动的,包括视图。

当用户再次打开它时,应用程序将不会重新加载所有的实例。相反,它将从内存中检索它们。这包括UI组件,如TextViews

onRestart()

由于活动的状态仍然存在,当用户重新启动活动时,onRestart() 方法可以被调用。这意味着该活动将回到主屏幕,用户可以继续与它的组件进行交互。

正如所讨论的,onCreate() 函数在一个活动的生命周期中只被调用一次。所以,当onRestart() 方法被执行时,活动将通过执行onStart() 然后onResume() 来恢复。

@Override
protected void onRestart() {

    Toast.makeText(this, "onRestart MainActivity", Toast.LENGTH_SHORT).show();
    Log.d(TAG, "onRestart MainActivity");

    super.onRestart();
}

onDestroy()

这是活动被停止时将收到的最后一个回调。

当配置状态(如屏幕旋转或语言设置)发生变化时,该方法被调用。Android系统将销毁该活动,然后用设定的配置重新创建它。

@Override
protected void onDestroy() {

    Toast.makeText(this, "onDestroy MainActivity", Toast.LENGTH_SHORT).show();
    Log.d(TAG, "onDestroy MainActivity");

    super.onDestroy();
}

测试该活动的生命周期

我们将执行这个应用程序,并阅读我们的Logcat消息,看看这些不同的方法是如何执行的。在这一点上,你的MainActivity.java 应该有以下代码。

MainActivity code

为了测试这个应用程序,我们将添加另一个活动,这样我们就可以在这些方法从A点变化到B点时读取它们。

在Android Studio中,创建另一个empty 活动并将其称为Activity2.java 我们将添加与MainActivity.java 文件中相同的代码。然而,我们将改变ToastLog 的信息,如下所示。

public class Activity2 extends AppCompatActivity {

    private static final String TAG = "Activity2";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_2);
        Toast.makeText(this, "onCreate Activity2", Toast.LENGTH_SHORT).show();
        Log.d(TAG, "onCreate Activity2");
    }

    @Override
    protected void onStart() {
        super.onStart();
        Toast.makeText(this, "onStart Activity2", Toast.LENGTH_SHORT).show();
        Log.d(TAG, "onStart Activity2");
    }

    @Override
    protected void onRestart() {
        super.onRestart();
        Toast.makeText(this, "onRestart Activity2", Toast.LENGTH_SHORT).show();
        Log.d(TAG, "onRestart Activity2");
    }

    @Override
    protected void onResume() {
        super.onResume();
        Toast.makeText(this, "onResume Activity2", Toast.LENGTH_SHORT).show();
        Log.d(TAG, "onResume Activity2");
    }

    @Override
    protected void onPause() {
        super.onPause();
        Toast.makeText(this, "onPause Activity2", Toast.LENGTH_SHORT).show();
        Log.d(TAG, "onPause Activity2");
    }

    @Override
    protected void onStop() {
        super.onStop();
        Toast.makeText(this, "onStop Activity2", Toast.LENGTH_SHORT).show();
        Log.d(TAG, "onStop Activity2");
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        Toast.makeText(this, "onDestroy Activity2", Toast.LENGTH_SHORT).show();
        Log.d(TAG, "onDestroy Activity2");
    }
}

在你的MainActivity中,添加以下方法来帮助我们在活动之间进行导航。

public void gotoActivity2(View view) {
    Intent intent = new Intent(this, Activity2.class);
    startActivity(intent);

}

上面的意图将帮助我们执行并导航到Activity2。为了执行这个方法,我们将在activity_main.xml ,如下图所示,添加一个按钮。

<TextView
    android:id="@+id/text"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="Watch the Log in Android Studio when you run the application"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintLeft_toLeftOf="parent"
    app:layout_constraintRight_toRightOf="parent"
    app:layout_constraintTop_toTopOf="parent"
    app:layout_constraintVertical_bias="0.056" />

<Button
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_marginTop="52dp"
    android:layout_marginEnd="50dp"
    android:layout_marginStart="50dp"
    android:layout_weight="50"
    android:onClick="gotoActivity2"
    android:text="go to Activity2"
    app:layout_constraintTop_toBottomOf="@+id/text"
    tools:layout_editor_absoluteX="15dp" />

这就是该应用程序在你的安卓设备上应该有的样子。

MainActivity screen)

在运行这个应用程序之前,确保你在Android Studio中打开Logcat窗口。

Logcat

应用程序启动后,立即按顺序执行以下方法。

First methods

该应用程序开始执行onCreate() 功能。在这个阶段,应用程序的组件还不可见。

然后,onStart() 方法被调用,接着是onResume() 。在这个生命周期中,用户可以与UI组件互动。

现在让我们通过点击go-to Activity2 按钮来导航到activity2

此刻,Activity2 正在阻止MainActivity 。这意味着MainActivity 将使用onPause() 的回调来暂停。这一点在下面被强调。

OnPause main activity

它表明当用户切换到Activity2MainActivity 被暂停。在这一点上,MainActivity 将被保存在一个回栈中。

Activity2 被带到前台时,onStop() 也将被调用到Mainctivity 。这是因为Android系统正在释放任何MainActivity 不使用的资源。

Switching activities logs

请注意,MainActivity并没有被销毁。这意味着它的状态被保存在内存中,我们可以检索到它们。要做到这一点,请导航回上一个活动,并观察Logcat消息。

OnRestart main activity

你可以看到,这里有三个方法被执行。onRestart(),onStart(), 和onResume()

当你back press ,这意味着你正在退出活动,回调将执行,如下所示。

OnDestroy main activity

正如你所看到的,当退出应用程序时,onDestroy() 不被首先调用。该活动仍然遵循其生命周期。

结论

作为一个开发者,你应该明智地选择当某个方法或回调被执行时要执行什么。你最终可能不会在一个应用程序中使用所有这些回调。