小白实战大前端:移动端与前端的互通之路
上QQ阅读APP看书,第一时间看更新

2.2.4 Activity的生命周期

Android系统中的“页面”(也就是Activity)的生命周期,与2.1.4节中介绍的HTML生命周期类似。图2-12为Android官方网站上的生命周期,图中已经较为清晰地表达了Android的Activity的生命周期流程。

图2-12 Activity的生命周期

表2-2为读者详细归纳了常用的6种生命周期状态:onCreate、onStart、onResume、onPause、onStop和onDestroy。

表2-2 Activity状态方法和具体用处

可能大家理解onPause和onStop这两个生命周期还有些困难,Activity被遮挡是一个什么样的页面状态呢?大家对此并没有很直观的感受,接下来我们先通过一个小例子来介绍一下onPause和onStop生命周期。

我们需要一个透明的Activity(TransparentActivity)来做onPause的遮挡实验,具体如代码清单2-14所示。

代码清单2-14 TransparentActivity实现

package com.example.chenchen.book;

    import android.app.Activity;
    import android.os.Bundle;

    public class TransparentActivity extends Activity {
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.transparent);
        }
}

上述代码其实是一个非常简单的Activity,但是可能有人会问:不是说遮挡的Activity吗?那应该是个透明的Activity或者展示一半的Activity?我们之前提到,项目中每添加一个新的Activity就要在AndroidManifest.xml文件中添加一个项目声明,如代码清单2-15所示。大家观察代码清单中第13行代码,即<activity android:theme="@android:style/Theme.Translucent" android:name=".TransparentActivity">,这行代码实际上除了声明TransparentActivity之外,还给这个Activity添加了一个主题(theme)——Theme.Translucent,它表示该Activity是一个全透明的Activity。

代码清单2-15 Activity的透明设置

<?xml version="1.0" encoding="utf-8"?>
    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
        package="com.example.chenchen.book">
        <application
            android:allowBackup="true"
            android:icon="@mipmap/ic_launcher"
            android:label="@string/app_name"
            android:roundIcon="@mipmap/ic_launcher_round"
            android:supportsRtl="true"
            android:theme="@style/AppTheme">
            <activity android:name=".MainActivity">
            </activity>
            <activity android:theme="@android:style/Theme.Translucent" android:name=".TransparentActivity">
            </activity>
            <activity android:name=".AActivity">
                <intent-filter>
                    <action android:name="android.intent.action.MAIN" />
                    <category android:name="android.intent.category.LAUNCHER" />
                </intent-filter>
            </activity>
            <activity android:name=".BActivity">
            </activity>
        </application>
</manifest>

紧接着我们需要在之前创建的TransparentActivity中添加一个布局文件——transparent.xml,其具体功能实现如代码清单2-16所示。TransparentActivity的内容只有一行文字,主要是为了在展示该Activity时告诉用户:此Activity是透明的。

代码清单2-16 transparent.xml布局文件

<?xml version="1.0" encoding="utf-8"?>
    <android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".MainActivity">

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="我是透明的Activity"
            android:textSize="20sp"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintTop_toTopOf="parent" />

</android.support.constraint.ConstraintLayout>

最后我们只需要更改一下代码清单2-12中的AActivity就可以完成这个实验了,具体更改之后的代码如代码清单2-17所示。首先我们在代码中加入了onPause和onStop这两个Activity中最常用的生命周期钩子,并且在对应的钩子中进行日志输出,紧接着添加了一个新的按钮事件,也就是button_toast按钮的事件,该事件完成了跳转透明Activity的操作。稍后将给大家演示onPause和onStop的触发操作。

代码清单2-17 添加跳转透明TransparentActivity之后的代码

package com.example.chenchen.book;
import android.app.AlertDialog;
import android.content.Intent;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.Button;
public class AActivity extends AppCompatActivity {
    AActivity mContext = this;
    private AlertDialog.Builder builder;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_a);
        Button button = findViewById(R.id.toB);
        Button button_toast = findViewById(R.id.toast);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent(AActivity.this,BActivity.class);
                mContext.startActivity(intent);
            }
        });
        button_toast.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {Intent intent= new Intent(mContext, Trans-parentActivity.class);
                startActivity(intent);
            }
        });
    }
    @Override
    protected void onPause() {
        Log.d("test_status","onPause");
        super.onPause();
    }
    @Override
    protected void onStop() {
        Log.d("test_status","onStop");
        super.onStop();
    }
}

在代码编写完毕后,直接运行这个实例,然后就会看到图2-13所示界面。与之前图2-10中内容不一样的地方是,图2-13中又多了一个“弹出透明ACTIVITY”按钮。

图2-13 AActivity界面

紧接着我们按下这个按钮,就会看到如图2-14,所展示的界面了。在图2-14中,我们可以观察到在手机界面中间又出现了一行字:“我是透明的Activity”,但是也能看到“我是AActivity”字样,其实这是透明的TransparentActivity压在了AActivity上的结果。

图2-14 跳转到TransparentActivity展示

这时候让我们观察一下日志打印,可以在onPause钩子和onStop钩子中看到打印出来的日志,如图2-15所示。我们在日志中发现,随着透明Activity的出现,并没有触发原来AActivity的onStop钩子,而是仅仅触发了onPause钩子,这就是我们之前说到的部分遮挡,所谓部分遮挡不仅仅是一个不透明的Activity遮挡了一部分Activity的情况,还包括这种透明模板的Activity的遮挡情况,即不管开发者在界面上看到完全透明的TransparentActivity遮挡下面的AActivity,还是只看到部分AActivity被遮挡,都只会触发onPause钩子,而不会触发onStop钩子。

图2-15 点击弹出透明Activity日志输出

提示

很多人认为Android自带的Dialog弹层也会触发onPause钩子,因为Dialog也遮挡了Activity,但是实际上普通的Dialog的弹出是没有办法触发Activity的onPause钩子的。

那么onStop日志到底什么时候会出现呢?让我们先回到图2-13所示的界面,然后点击“跳转到B”按钮。然后观察一下控制台,就会看到如图2-16所示的输出日志。

图2-16 点击“跳转到B”按钮的日志输出

我们可以观察到控制台输出了一个onPause,紧接着输出了一个onStop。这就是BActivity(不透明的Activity)完全遮挡了AActivity,所以会触发onStop钩子。触发onStop的情况下就一定会触发onPause,因为完全遮挡之前,势必会先出现部分遮挡的状态,但是触发onPause的时候不一定会触发onStop。

Android端的Activity的生命周期就介绍完了,我们将在2.3节中进行一些前端与移动端页面属性以及生命周期的对比,并且提供微型电商的基础页面代码。