Android筆記(19):Activity

Photo by Đức Trịnh on Unsplash


Activity 是 Android 很重要的一個組件,主要用在與使用者互動時的入口點或用戶界面,類似 VB 或 C# 開發工具的 Form,例如:使用 Line 與朋友聊天是一個 Activity,切換到主頁或貼圖下載時,則又是另一個 Activity,這時有人撥電話進來,顯示的電話接聽畫面又是另一個 Activity,如果應用程式有多個 Activity ,就需要將其中一個 Activity 標記為主要 Activity,也是用戶啟動應用程式時出現的第一個畫面。且在 Activity 中可以啟動另一個 Activity,以執行不同功能的操作。

[Activity生命週期]

如果曾寫過 C/C++ 程式語言的朋友,會知道一般程序是從 main()函數開始,而 Android 系統則經由 Activity 的 onCreate()方法開始進入程序。Activity 在應用程式的過程中,從開始到結束,甚至從記憶體中刪除,這些程序稱做「Activity生命週期」,這個生命週期的觀念與程式編寫有很大的關係,設計者必須在使用者操作到某種情境時(如建立、暫停等),執行特定的語法來與使用者互動,先從以下這張圖說起:

Android 系統的 Activity 主要有 4 個狀態:活動狀態(Active/Running)、暫停狀態(Paused)、停止狀態(Stopped)及銷毀狀態(Dead/Inactive),如上圖彩色的橢圓形框,7 個方法:onCreate()、onStart()、onResume()、onPause()、onRestart()、onStop()及 onDestroy(),如上圖方形框。說明如下:
4種狀態說明
活動狀態(Active/Running)當 Activity 位於螢幕的最上面時的狀態,同一個時間只會有一個 Activity 處於活動(Active)
或運行(Running)狀態,其他 Activity 會處於 Dead、Stopped 或是 Paused 狀態。
暫停狀態(Paused)當 Activity 失去焦點的狀態,畫面仍然可見時,此時的狀態變成 Paused。此時的 Activity
只是失去與使用者互動的畫面,其所有的狀態及資訊都還存在。
停止狀態(Stopped)當 Activity 完全不可見時的狀態,但仍然保存所有的狀態和資訊。當記憶體低的情況下,
它將會被系統killed(殺死)。
銷毀狀態(Dead/Inactive)當 Activity 被系統回收掉時,此時就是處於 銷毀狀態,所佔用的記憶體回收。

在 Activity 狀態改變時,會呼叫不同的方法來因應,總計 7 個方法,如以下說明。
方法說明
onCreate當 Activity 被建立時候會自動執行 onCreate 方法來進行一些初始化動作,且只會執行一次。
onStart在 onCreate 或 onRestart 方法執行完成後,就由 onStart 接手繼續將 activity 的 UI 物件初始化與可視化,
當 Activity 在前臺顯示時,會執行 onResume。
onResumeonResume 的階段是應用程式持續處於執行中,且與使用者互動進行中,直到使用者的切換到其他 Activity 頁面,
或開啟其它應用程式,如接到其他人來電,這時就會進入 onPause 暫停的狀態。
onPause系統要執行另一個活動時,或原 Activity 可見但失去焦點時觸發。
onRestart將 Activity 從 onStop 狀態喚醒時會用 onRestart 方法,這個方法會比再次執行 onStart 好。執行完 onRestart 之後
執行 onStart。
onStop當這個 Activity 完全無法呈現在 UI 時,會呼叫 onStop 方法。有三種情況會呼叫 onStop()方法:
(1) 一個新的 Activity 被執行,
(2) 一個已經存在的 Activity 被切換到最前端。
(3) 這個 Activity 要被銷燬。
如果使用者要重新開始這個 Activity,則會呼叫 onRestart方法;若這個 Activity 要被銷毀,則呼叫 onDestroy 方法。
onDestroy當 Activity 銷毀前會呼叫 onDestroy 方法,如 Activity 呼叫了 finish() 方法來結束這個 Activity,
或因為系統為了節省空間而銷毀這個 Activity。


[建立 Activity]

建立 Activity 有兩個方法,一是在 Android Studio 建立,另一個是使用 java 程式建立,建立新的 Activity 之後,如要使用新建立的 Activity 有兩個方法,一是在啟動設定檔 AndroidManifest.xml 檔中,定義啟動時預設的 Activity,但這只能設定一個 Activity,無法由一個 Activity 去開啟另一個 Activity,這時需要 java/kotlin 來開啟其他的 Activity。另一個方法就是直接使用 java 指令來開啟 Activity。

在 Android 應用程式中,若存在多個 Activity 時,可使用 startActivity() 方法來啟動其他的 Activity。startActivity()的語法格式如下:
public void startActivity (Intent intent) 
這裡使用 Intent 類別當作參數,Intent 是 Android 應用程式中在各組件間的通信方式。有關 Intent 物件的建立與應用,留待稍後的文章來瞭解。以下是建立 Activity 的步驟與方法:

方法一:使用 Android Studio 建立
Activity 放在 res\layout 目錄下,對著 layout 按右鍵 →「New」→「Activity」→ (選擇 Activity 的樣版),一般選擇「Empty Activity」,依自己的情況建立不同的模版。如下圖;
選擇模版後,出現以下視窗,輸入 Activity 名稱、Layout 名稱等,按下  Finish  就完成了。

方法二:使用 java 程式建立
(1) 建立的 Activity 一般是繼承自 android.app 套件中的 Activity 類別,或是繼承自 Activity 的子類別。如要建立一個名為 MyActivity 的 Activity,程式如下:
import android.app.Activity;
public class MyActivity extends Activity {

}

(2) 建立 Activity 後,通常需要重寫呼叫的方法,檔這些方法是文章上一段提到的 Acticity 生命週期的七個方法,一般都需要重寫 onCreate(),在這個階段打開佈局 Layout檔,並在這個方法中使用 setContentView() 來設定要顯示的頁面,這個頁面是一個佈局的 XML 名稱。例如,在步驟(1)中建立的 Activity 中,重寫 onCreate() 方法,並設定要顯示的頁面為 activity_my_layout.xml,程式碼如下:
@Override 
public void onCreate(Bundle savedInstanceState) {
   super.onCreate(savedInstanceState); 
   setContentView(R.layout.activity_my_layout); 
}
setContentView(R.layout.activity_main)方法是 android.app.Activity 類別提供的方法,用來設定 Activity 本身的畫面配置資源,在 Activity 中存取資料需透過「R」類別,R 類別代表應用程式內的資源。


[設定 Activity]

使用 Android Studio 建立新的 Activity 後,會自動在 AndroidManifest.xml 檔中建立這個 Activity 的設定。如果沒有在 AndroidManifest.xml 檔中設定 Activity 標記,而又在程式中啟動新的 Activity,將會出現異常資訊。設定 Activity 標記的方法是在<application>與</application>標記中間增加<activity>和</activity>標記,格式如下:
<activity 
android:name="實現類"
android:label="說明的文字"
android:theme="要應用的主題" … >
</activity>


[關閉 Activity]

在Android 中,如果要關閉目前的 Activity,只要使用 Activity 類別提供的 finish()方法即可。finish() 語法格式如下:
public void finish() 


[Activity應用情境]

以下幾種執行 Activity 啟動時、按下 Home 鍵及退回主畫面時,Actvity 呼叫方法的順序,如以下說明:

(1) 啟動 Ativity
Activity啟動後,首先調用 onCreate 方法,然後是 onStart 方法,最後是 onResume 方法,進入運行狀態,此時 Activity 顯示在畫面。Activity 執行方法的過程:Activity 啟動 → onCreate() → onStart() → onResume()依次被呼叫。

(2) 當前 Activity 執行中,按 Home 鍵回到主畫面
在當前的 Activity 點擊 Home 回到主畫面,此時 onPause 方法和 onStop 方法被執行,也就是點擊 Home 鍵回到主畫面,Activity 執行方法的順序為:→ onPause() → onStop() 依次被呼叫。

(3) 當點擊 Home 鍵回到主畫面後,再次點擊 App 回到 Activity
重新再回到 Activity 時,調用了onRestart 方法,onStart 方法,onResume 方法。Activity 執行方法的順序為:→ onRestart() → onStart() → onResume() 依次被呼叫。

(4)在原有的 Activity 再開啟新的 Activity
原來的 Activity 呼叫了 onPause 方法和 onStop 方法。原 Activity 執行方法的順序為:→ onPause() → onStop(),跟點擊 home 鍵時的順序是一樣的。有點需要注意的是,如果新的 Activity 使用了透明主題,那麼當前 Activity 不會呼叫 onStop 方法。在新的 Activity 其呼叫的方法被觸發前,要等原 Activity 的 onPause 方法執行結束後才會被呼叫。

(5) 點擊 Back 鍵退回時
當點擊 Back 鍵退回時,相當於退出了當前 Activity,Activity 將被銷毀,退出當前 Activity 執行方法的順序為:→ onPause() → onStop() → onDestroy() 依次被呼叫。


[程式範例]

(1) 新建一個模組 Module,使用上述方法一建立一個新的 Activity,名為 DetailActivity。
(2) 開啟 manifests 目錄,打開 AndroidManifest.xml,在新增的 DetailActivity 標記加上 label 名稱。如下圖:
(3) 進入 res/layout 目錄下點選佈局檔 activity_main.xml。將預設的內容刪除,建立 2 個 TextView 文字框顯示帳號/密碼,2 個編輯框,2 個按鍵,以下是完整 XML 的內容。
<?xml version="1.0" encoding="utf-8" ?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:padding="8dp"
    android:orientation="vertical" >

    <TextView
        android:id="@+id/acc"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="20sp"
        android:textSize="22sp"
        android:text="帳號: " />

    <EditText
        android:id="@+id/acc"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="10sp"
        android:textSize="22sp"
        android:text="請輸入帳號 " />

    <TextView
        android:id="@+id/pwd"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="20sp"
        android:textSize="22sp"
        android:text="密碼: " />

    <EditText
        android:id="@+id/acc"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="10sp"
        android:textSize="22sp"
        android:text="請輸入密碼 " />

    <Button
        android:id="@+id/cfm"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="30sp"
        android:textSize="22sp"
        android:text="確定" />

    <Button
        android:id="@+id/forget"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="10sp"
        android:textSize="22sp"
        android:text="忘記密碼" />
</LinearLayout>
(4) 進入 java 目錄下,開啟 MainActivity.java 程式,用 findValueById 連結 Button 元件,設定 setOnClickListener 監聽器,在 onClick 的方法內新增 Intent 實例,再執行 startActivity 開啟 DeatailActivity。程式如下:
package com.example.app2;

import androidx.appcompat.app.AppCompatActivity;

import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;

public class MainActivity extends AppCompatActivity {

    private Button forget;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        forget  = (Button) findViewById(R.id.forget);
        forget.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent(MainActivity.this,DetailActivity.class);
                startActivity(intent);
            }
        });

    }
}
新增的是下圖紅框處:

執行的結果如下:


[參考資料]

Post a Comment

較新的 較舊