- 小白實戰大前端:移動端與前端的互通之路
- 陳辰
- 1496字
- 2022-06-28 16:19:34
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節中進行一些前端與移動端頁面屬性以及生命周期的對比,并且提供微型電商的基礎頁面代碼。