บทที่ 6 Activity, Toast, Activity Lifecycle และการเขียนคำสั่งดักจับเหตุการณ์

Ponglang Petrung
8 min readDec 3, 2022

Activity คือ Application Component ที่ทำหน้าที่ควบคุมการแสดงผล User Interface รวมถึงควบคุมการมีปฏิสัมพันธ์ระหว่างผู้ใช้กับ User Interface ด้วย เช่น การโทรออก, การถ่ายรูป, การส่งอีเมล์ เป็นต้น

โดยปกติแล้ว ใน Application หนึ่ง ๆ จะมี Activity มากกว่าหนึ่ง Activity เสมอ ซึ่งแต่ละ Activity ก็จะมีหน้าที่ที่แตกต่างกันไป เช่น Activity สำหรับควบคุมหน้าจอแสดงรายชื่ออีเมล์, Activity สำหรับควบคุมหน้าจอแบบฟอร์มเพื่อส่งอีเมล์ เป็นต้น และในแต่ละ Activity ใด ๆ ก็สามารถสั่งให้ Activity อื่น ๆ ทำงานได้เสมอ

อย่างไรก็ตาม ในช่วงเวลาหนึ่ง ๆ จะมีเพียง Activity เดียวเท่านั้นที่พร้อมมีปฏิสัมพันธ์กับผู้ใช้ นั่นหมายถึงเมื่อมี Activity ใด ๆ เริ่มทำงานขึ้นมาใหม่ จะทำให้ Activity เดิมที่กำลังทำงานอยู่เปลี่ยน State ของตนเองไป ซึ่ง State หลัก ๆ ของ Activity ได้แก่ Create, Start, Resume, Pause, Stop, และ Destroy ทั้งนี้เพื่อควบคุมการทำงานของ Activity ให้เหมาะสมกับ State ที่เปลี่ยนไปนั้น จะต้องเขียนคำสั่งไว้ภายใน LifeCycle Callback Method ต่าง ๆ เพื่อควบคุมการทำงานของแต่ละ State นั้น ๆ เช่น onCreate ( ) เป็น LifeCycle Callback Method ที่จะถูกทำงานเมื่อ Activity เปลี่ยน State มาเป็น Create, onStart ( ) เป็น LifeCycle Callback Method ที่จะถูกทำงานเมื่อ Activity เปลี่ยน State มาเป็น Start เป็นต้น

Activity ถือเป็นหนึ่งในสิ่งที่ออกแบบมาได้อย่างยอดเยี่ยมบนแอนดรอยด์เลยก็ว่าได้ ด้วยความสามารถในการจัดการการใช้งานหน่วยความจำได้อย่างมีประสิทธิภาพของมันจนระบบ Multitasking สามารถทำได้อย่างสมบูรณ์แบบบนแอนดรอยด์นั่นเอง

การใช้ Intent เพื่อเปิดหน้า Activity และส่งข้อมูลระหว่าง Activity

ในกรณีที่ App ของเรามี Activity (ส่วนแสดงผล) มากกว่า 2 หน้าจอ ผู้อ่านสามารถควบคุมการเปลี่ยน
ส่วนแสดงผลไป-มาระหว่าง Activity ได้อีกด้วย โดยอยู่ในความรับผิดชอบของคลาส Intent
ตัวอย่างที่ 5–2 การสร้างส่วนแสดงผลที่มี 2 Activity และปุ่มเปลี่ยนส่วนแสดงผลไป-มา มีขั้นตอนดังนี้
1. สร้างโปรเจ็กต์ Android เวอร์ชัน 5 ตั้งชื่อว่า MultipleActivity
2. โดยปกติแล้วเมื่อสร้างโปรเจ็กต์ Android ขึ้นมา สิ่งที่เราได้มาโดยอัตโนมัติคือ
ส่วนแสดงผล อยู่ในความรับผิดชอบของไฟล์ XML ที่ชื่อว่า activity_main.xml เก็บอยู่ใน
พาธ \res\layout
โค้ด JAVA สำหรับเขียนโค้ดให้กับหน้าจอที่ 1 อยู่ในไฟล์ที่ชื่อว่า MainActivity.java เก็บอยู่
ในพาธ \src\ชื่อ package ของโปรเจ็กต์ปัจจุบัน

หน้า Layout

หน้า activity_main.xml จะออกแบบดังนี้

<RelativeLayout xmlns:android=”http://schemas.android.com/apk/res/android"
android:layout_width=”match_parent”
android:layout_height=”match_parent” >

<Button
android:id=”@+id/button_about”
android:layout_width=”wrap_content”
android:layout_height=”wrap_content”
android:text=”About”
android:paddingTop=”24dp”
android:paddingBottom=”24dp”
android:paddingLeft=”48dp”
android:paddingRight=”48dp”
android:layout_centerVertical=”true”
android:layout_centerHorizontal=”true”/>

<ImageView
android:layout_width=”128dp”
android:layout_height=”128dp”
android:id=”@+id/imageView”
android:src=”@mipmap/ic_launcher”
android:layout_centerHorizontal=”true”/>

</RelativeLayout>

หน้า activity_about.xml

<RelativeLayout xmlns:android=”http://schemas.android.com/apk/res/android"
android:layout_width=”match_parent”
android:layout_height=”match_parent”>

<TextView
android:text=”AboutActivity”
android:layout_width=”wrap_content”
android:layout_height=”wrap_content”
android:textSize=”36sp”
android:layout_marginTop=”32dp”
android:layout_alignParentTop=”true”
android:layout_centerHorizontal=”true”/>

<Button
android:id=”@+id/button_back”
android:layout_width=”wrap_content”
android:layout_height=”wrap_content”
android:text=”Back”
android:paddingTop=”24dp”
android:paddingBottom=”24dp”
android:paddingLeft=”48dp”
android:paddingRight=”48dp”
android:layout_centerVertical=”true”
android:layout_centerHorizontal=”true”/>

</RelativeLayout>

โดยเริ่มจากสร้าง ปุ่ม Button จาก MainActivity แล้วให้ทำการเปิด AboutActivity ขึ้นมา จากนั้นหน้า AboutActivity เมื่อกด Back ก็จะกลับมาหน้า MainActivity อีกครั้ง

โดยใช้เพิ่มโค๊คสองบรรทัดนี้ลงไป ใน onClickListener คือเมื่อทำการกดปุ่มก็จะเปิด AboutActivity ขึ้นมา นั่นเอง

Intent intent = new Intent(this, AboutActivity.class);
startActivity(intent);

จากนั้นให้สร้างออปเจ็ค intent ขึ้นมา โดยรับ parameter 2 ตัว ตัวแรกคือ Context ภายใน Activityแรก และ parameter ตัวที่สองคือ Activity ที่ต้องการเปิด code เต็มๆของ MainActivity คือ

package com.exmple.myfirstapp;

import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.TextView;

public class MainActivity extends AppCompatActivity {

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

Intent intent = new Intent(this, AboutActivity.class);
startActivity(intent);
}
}

ส่วนฝั่ง AboutActivity เมื่อกดปุ่ม back ก็จะกลับมา Activity จะใช้ finish() หมายถึงการปิด Activity แต่ถ้าต้องการไปหน้าเดิมก้ให้ใส่ code เดิมโดยเปลี่ยนจาก AboutActivity มาเป็น MainActivity

Intent intent = new Intent(this, MainActivity.class);
startActivity(intent);

มันก็จะเปิดหน้า MainActivity ได้ แต่ว่ามันจะมีหน้าซ้อนกัน 2 หน้า (โดยปกติใน Android Activity มันจะถูกเปิดซ้อนกันไปเรื่อยๆ)

Code จะ class AboutActivity.java

package com.exmple.myfirstapp;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;

public class AboutActivity extends AppCompatActivity {

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

Button buttonBack = (Button) findViewById(R.id.button_back);

buttonBack.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
finish();
}
});
}
}

การรับ-ส่งข้อมูลระหว่าง Activity

วิธีการส่งข้อมูลข้าม Activity กรณีมีข้อมูลอยู่ MainActivity แต่อยากให้มันไปโชว์ทีหน้า DetailActivity ว่าจะทำอย่างไร? ได้บ้าง

วิธีการ ก็คือใช้ Intent เหมือนเดิมครับ โดยทาง Intent จะมีเมธอด putExtra(key, value) มาให้สำหรับส่งค่าไปครับ parameter แรกจะเป็นชื่อเรียก ส่วน parameter สอง จะเป็นชนิดของตัวแปร จะเป็น int, String, boolean, float ก็ได้ครับ ดังเช่นตัวอย่าง
การสร้าง Android App ที่มีตั้งแต่ 2 Activity ขึ้นไป ย่อมที่จะต้องมีการติดต่อรับ-ส่งข้อมูลจาก Activity
หนึ่งไปสู่ Activity หนึ่ง ผู้อ่านสามารถนำอมูลที่รับ-ส่งระหว่างกันไปใช้ในการทำงานในระดับถัดไปนั่นเอง
ตัวอย่างการรับ-ส่งข้อมูลระหว่าง Activity มีขั้นตอนดังนี้
1. สร้างโปรเจ็กต์ Android เวอร์ชัน 6 ตั้งชื่อว่า SendData
2. ผู้เขียนใช้ส่วนแสดงผลที่ชื่อว่า activity_main.xml ทำหน้าที่ส่งข้อมูล และใช้ส่วนแสดงผลที่ชื่อว่า
secondscreen.xml ทำหน้าที่รับข้อมูล
3. ออกแบบส่วนแสดงผลในไฟล์ activity_main.xml ซึ่งทำหน้าที่ส่งข้อมูล ดังรูปที่

และเมื่อแสดงไฟล์ Xml

<LinearLayout xmlns:android=”http://schemas.android.com/apk/res/android"
xmlns:tools=”http://schemas.android.com/tools"
android:id=”@+id/LinearLayout1"
android:layout_width=”match_parent”
android:layout_height=”match_parent”
android:orientation=”vertical”

tools:context=”.MainActivity” >
<EditText
android:id=”@+id/edtFullName”
android:layout_width=”match_parent”
android:layout_height=”wrap_content”
android:layout_marginTop=”15dp”
android:ems=”10"
android:inputType=”textPersonName” >
<requestFocus />
</EditText>

<EditText
android:id=”@+id/edtAddress”
android:layout_width=”match_parent”
android:layout_height=”wrap_content”
android:layout_marginTop=”15dp”
android:ems=”10"
android:inputType=”textPersonName” />
<Button
android:id=”@+id/cmdSend”
android:layout_width=”match_parent”
android:layout_height=”wrap_content”
android:text=”Send” />
</LinearLayout>

ให้ผู้อ่านเพิ่ม Android XML Layout File เข้ามาอีก 1 ไฟล์ ตั้งชื่อว่า secondscreen.xml ทำหน้าที่
รับข้อมูล กำหนดให้ใช้ LinearLayout แบบแนวตั้ง (แอตทริบิวต์ android:orientation เท่ากับ
vertical) ใช้ TextView จำนวน 3 ตัว ดังสคริปต์ XML ต่อไปนี้

<?xml version=”1.0" encoding=”utf-8"?>
<LinearLayout xmlns:android=”http://schemas.android.com/apk/res/android"
android:layout_width=”match_parent”
android:layout_height=”match_parent”
android:orientation=”vertical” >
<TextView
android:id=”@+id/textView1"
android:layout_width=”wrap_content”
android:layout_height=”wrap_content”
android:text”ข้อความ” />
<TextView
android:id=”@+id/tvFullName”
android:layout_width=”wrap_content”
android:layout_height=”wrap_content” />
<TextView
android:id=”@+id/tvAddress”
android:layout_width=”wrap_content”
android:layout_height=”wrap_content” />
</LinearLayout>

ทดสอบการทำงานได้ผลลัพธ์ดังรูป

ในไฟล์ MainActivity.java ซึ่งเป็นของหน้าจอส่งข้อมูล (activity_main.xml) ให้เขียนโค้ด JAVA
เพื่อกำหนดการทำงานดังต่อไปนี้

การส่งข้อมูลข้าม Activity

เนื่องจากว่า Activity ถูกสร้างมาเพื่อใช้งานที่ต่างกันออกไปตามแต่ละหน้า บ้างก็ถูกสร้างมาเพื่อทำงานกับ Intent ที่ถูกส่งมาโดยเฉพาะ หากมีส่งมา 4 Intents ก็ควรจะสร้างมา 4 หน้าจอ เช่นหน้า Compose Email ของ Email Client หรือบ้างก็ถูกสร้างมาเพื่อเป็นหน้าจอเดียว ไม่ควรสร้างหน้าเพิ่ม ยกตัวอย่างเช่นหน้า Email Inbox นั่นเองการกำหนดว่า Activity ที่จะถูกเรียกขึ้นมาแสดงบนหน้าจอนั้นจะต้องถูกสร้างใหม่หรือจะใช้ตัวที่เคยสร้างไว้แล้วจึงถือเป็นเรื่องสำคัญ มิฉะนั้นอาจจะเกิดการทำงานที่ผิดพลาดได้ launchMode จึงเกิดมาเพื่อการนี้ มีไว้กำหนดว่า Activity นั้นๆจะถูกเรียกขึ้นมาในแบบไหน รวมถึง Activity ที่ถูกเด้งขึ้นมาจะอยู่บน Task ไหน

<activity

android:name=”.SingleTaskActivity”

android:label=”singleTask launchMode”

android:launchMode=”singleTask”>

โดย launchMode มีอยู่ 4 โหมดด้วยกัน ดังต่อไปนี้ หมวด standard

โหมดนี้เป็นโหมดที่ถูกกำหนดให้เป็นโหมด Default ในกรณีที่ไม่กำหนด launchModeลักษณะการทำงานของ Activity ในโหมดนี้คือ จะสร้าง Activity ใหม่เสมอ ใช้ในกรณีที่ต้องการสร้างหน้าจอให้มาตอบรับการทำงานแตกต่างกันไปทุก Intent ยกตัวอย่างเช่น หน้า Compose Email ที่ควรจะเด้ง Activity อันใหม่เพื่อรับ Intent การพิมพ์อีเมลใหม่เสมอ ถ้ามีส่งมา 10 Intents ก็ควรจะเด้งมา 10 หน้าที่ต่างกันไป ผลคือระบบสามารถมี Activity ชนิด standard กี่ตัวเปิดอยู่ก็ได้นั่นเอง ตามรูป

หมวดที่ 2 singleTop

โหมดต่อไปคือโหมด singleTop ที่โดยรายละเอียดแล้วจะคล้ายกับ standard คือสามารถมีได้มากกว่า 1 Activity รันในระบบ ทำงานต่างกันไปตาม Intent ที่ส่งเข้ามา แต่ต่างกันตรงที่ถ้า Task นั้นๆมี Activity ที่จะเรียกอยู่บนตำแหน่งบนสุดของ Stack อยู่แล้ว ก็จะไม่สร้าง Activity ใหม่อีก ส่วน Intent ที่ยิงมาจะถูกส่งไปยังคำสั่ง onNewIntent() ใน Activity ที่มีอยู่แล้วแทน

ด้วยเหตุนี้ ใน Activity ที่ถูกกำหนดให้ทำงานในโหมด singleTop จึงจำเป็นต้อง Handle Intent ทั้งจาก onCreate() และ onNewIntent() เพื่อให้ทำงานได้อย่างสมบูรณ์

หมวดที่ 3 singleTask

โหมดนี้จะถือว่าแตกต่างจาก standard และ singleTop ไปพอสมควรเพราะ โหมด singleTask นั้นจะอนุญาตให้มี Activity นั้นๆแค่เพียง 1 อันในระบบ (เทียบได้กับ Singleton) หากมี Activity นั้นๆเปิดอยู่ใน Task ใด Task หนึ่ง ระบบจะนำ Activity พร้อมทั้ง Task ที่ถือ Activity อยู่ทั้ง Task มาแสดงบนหน้าจอทันที พร้อมยิง Intent เข้า onNewIntent() แต่ถ้าไม่มี ก็จะสร้างใหม่ให้พร้อมแตก Task ใหม่ให้ทันทีในกรณีที่เป็นการยิง Intent มาจากแอปฯอื่น

ตัวอย่างการใช้งานของโหมดนี้ก็คือหน้าที่เราตั้งไว้เป็น Entry Point เช่น หน้า Inbox ของ Email Client หรือหน้า Timeline ของ Social Network อย่าง Facebook เป็นต้น ซึ่งหน้าพวกนี้ถ้าจะยอมให้เปิดได้หลาย Activity ก็ดูแปลกอยู่ ดังนั้น singleTask จึงถือเป็นอีกโหมดที่ใช้บ่อยพอสมควรแต่ก็ต้องใช้อย่างระวังเพราะเป็นโหมดที่มีเปิดโอกาสให้ Activity ที่อยู่เหนือ singleTask ถูกทำลายทิ้งได้ ถือว่าหมวดนี้สำคัญที่สุดของการใช้เลยก็ว่าได้

หมวดที่ 4 singleInstance

เป็นโหมดที่ใกล้เคียงกับ singleTask คือ Activity มีได้แค่ตัวเดียวในระบบ แต่ที่ต่างกันคือ Task ที่ถือครอง Activity ประเภทนี้จะสามารถถือ Activity ได้แค่ตัวเดียวเท่านั้น หากมีการเรียก Activity อื่นเพิ่ม ระบบจะสร้าง Task ใหม่ขึ้นมาทันที หรือถ้าเดิม Task มีอยู่หลาย Activity แล้วมาเรียก singleInstance Activity ระบบก็จะแตก Task ใหม่ให้เช่นกันอย่างไรก็ตาม ผลที่เกิดขึ้นค่อนข้างประหลาดคือถึงจะแตกออกเป็น 2 Tasks เมื่อดูจาก dumpsys แต่ใน Task Manager กลับเห็นแค่ตัวเดียว ขึ้นอยู่กับว่า Task ไหนที่ถูกสร้างขึ้นมาล่าสุด ส่วนอีก Task ถึงจะมองไม่เห็น แต่ทุกอย่างก็ทำงานอยู่ และไม่สามารถสลับกลับมาได้ด้วยนอกจากจะกดเปิดแอปฯจาก Launcher ใหม่ ส่งผลให้การทำงานแปลกออกไปและขัดต่อความรู้สึกเอามากๆ

Activity Life Cycle

การจัดการเกี่ยวกับวัฏจักร Activity (Activity Lifecycle) ของ app

ขณะที่ผู้ใช้เปิดใช้งาน -> ออกจาก app -> แล้วก็กลับเข้ามาใน app อีกครั้ง activity จะมีการย้าย state ต่างๆ เกิดขึ้นในวัฏจักร activity ยกตัวอย่างเช่น เมื่อ activity เริ่มทำงานครั้งแรก ก็จะแสดงขึ้นมาอยู่ด้านบนสุดของระบบ (foreground) และรอรับการทำงานจากผู้ใช้ ในระหว่างกระบวนการนี้ ระบบจะมีการเรียกใช้งาน callback method ต่างๆ(callback method = method ที่ถูกเรียกใช้งานอัตโนมัติ) ใน activity ที่ได้กำหนดการทำงานให้กับ UI และสวนติดต่ออื่นๆ ไว้ ถ้าผู้ใช้มีการใช้งานใดๆ ที่เป็นการเรียก activity อื่นขึ้นมา หรือสลับไปใช้งาน app อื่น

ระบบก็จะเรียก callback method อีกอันขึ้นมา เช่น ซ่อน app ไว้ด้านหลัง background (ไม่แสดง activity แต่ instance และ state นั้นยังทำงานอยู่)

ภายใน callback method เราสามารถกำหนดการทำงานใน activity เมื่อผู้ใช้ออกจาก app และกลับเข้ามาใช้งาน app ใหม่อีกครั้งได้ ตัวอย่าง ถ้า app เราเป็น app streaming video อาจจะสั่งให้ทำการหยุด video ชั่วคราว และปิดการเชื่อมต่อ network ไว้ก่อนเมื่อผู้ใช้สลับไปใช้ app อื่นและทันทีที่ผู้ใช้กลับมาใช้งาน app ต่อ ก็ให้ทำการเชื่อมต่อกับ network และก็อนุญาตให้ผู้ใช้กลับไปเล่น videoในตำแหน่งที่ค้างต่อไปทันทีได้ โดยที่ไม่ต้องเริ่มต้นใหม่ แบบนี้เป็นต้น

ในขณะที่ activity ทำงาน ระบบจะเรียกใช้ callback method ตามลำดับในลักษณะที่คล้ายกับการก่อพีระมิด นั่นก็คือ แต่ละขั้นตอนวัฏจักรของ activity ก็คือส่วนแยกย่อยแต่ละขั้นของพีระมิดเช่นว่า เมื่อระบบสร้าง instance ของ activity ขึ้นมาใหม่ method ที่เรียกใช้งานอัตโนมัติ (callback method)ก็จะขยับ activity state ขึ้นมาด้านบน ด้านบน พีระมิด คือจุดที่ activity กำลังทำงาน แสดงอยู่ด้านหน้าสุด และผู้ใช้ กำลังใช้งานอยู่ และเมื่อผู้ใช้กำลังจะออกจาก activity ระบบจะก็เรียกใช้ method อื่น ซึ่งก็ทำให้ activity stateถอยกลับไปอยู่ด้านล่างของพีระมิดตามลำดับเพื่อค่อยๆถอน activity ออกไป ในบางกรณี activityจะย้ายลงมาอยู่บางจุดและรอจังหวะที่จะถูกเรียกกลับขึ้นมาด้านบนอีก
( กรณีเช่นเมื่อผู้ใช้สลับไปใช้งาน app อื่น แล้วกลับมาใช้งาน )

  • Activity Launched คือสถานะที่เกิดขึ้นเมื่อ User เปิดใช้งาน App ซึ่ง Activity ที่ถูกกำหนดให้ Launch ได้ของ App นั้น ๆ จะถูกเรียกใช้งาน ซึ่งจะทำให้ Method onCreate(), onStart() และ onResume() ใน Activity นั้น ทำงาน
  • Activity running คือสถานะที่ User กำลังเล่นอยู่บน App
  • หากว่า Activity ถูกบดบังบางส่วน จะทำให้ Method onPause()ทำงาน หากกลับเข้าสู่ App จะทำให้ Method onResume() ทำงาน
  • และถ้าถูกบนบังจนหมด จะทำให้ Method onStop() ทำงานต่อจาก onPause() หากกลับเข้าสู่ App จะทำให้ Method onRestart(), onStart() และ onResume() ทำงาน
  • และเมื่อ User ออกจาก App จะทำให้ Method onDestroy() ทำงาน
  • Activity shut down คือสถานะที่ Activity ถูกเลิกใช้งานแล้ว
  • App process killed คือสถานะที่ App ถูก Kill โดยระบบ (เฉพาะกรณีเมื่อ Activity อยู่ในสถานะ Stop) เนื่องจากระบบต้องการ Memory หาก User กลับเข้าสู่ App จะทำกลับไปเริ่มต้นทำงานใหม่ที่ Method onCreate()

รูปจาก : http://developer.android.com/reference/android/app/Activity.html#ActivityLifecycle

รูปแสดงวัฏจักรของ activity ในรูปแบบโครงสร้างพีระมิด โดยแสดงให้เห็นว่า method ที่เรียกใช้

งานอัตโมัติ ( callback method:: onCreate() onStart() onResume() onRestart() ) จะขยับ activity ขึ้นไปด้านบนสุดที่ resumed stateและก็มี method ( callback method:: onPause() onStop() onDestroy() ) ที่จะขยับ activity ลงมาด้านล่าง activity ยังสามารถกลับไปที่ตำแหน่ง resumed state จากตำแหน่ง Paused และ Stopped ได้อีกด้วย

อาจจะไม่จำเป็นต้องเรียกใช้งาน callback method ทั้งหมดก็ได้ ขึ้นกับความซับซ้อนของactivity อย่างไรก็ตามเป็นสิ่งสำคัญที่เราจะควรทำความเข้าใจแต่ละ method เพื่อให้มั่นใจได้ว่า app ของเราตอบสนองเป็นไปตามที่ผู้ใช้คาดหวัง ดังนั้นการใช้งาน callback methodที่ถูกวิธีก็จะช่วยให้ app ของเราทำงานได้ดี รวมถึงสิ่งต่อไปนี้ด้วย

  • ไม่หยุดการทำงานหรือค้าง กรณีมีสายโทรเข้าหรือมีการสลับไปใช้งาน app อื่น
  • ไม่ใช้ทรัพยากรที่มีค่าของระบบอย่างสูญเปล่า ถ้าไม่มีการใช้งาน activity ใดๆ
  • ไม่กระทบต่อกระบวนการในขั้นตอนการใช้งานของผู้ใช้กรณีออกจาก app แล้วกลับเข้ามาอีกครั้ง
  • ไม่หยุดการทำงานหรือระบบค้าง กระทบการใช้งานของผู้ใช้กรณีมีการหมุนหน้าจอแนวนอนและแนวตั้ง

สิ่งที่จะได้รู้ต่อไปคือ มีหลายเหตุการณ์ที่ activity มีการเปลี่ยน state ต่างๆ ตามแสดงในรูปด้านบน

แต่มีอยู่ 3 state เท่านั้น ที่ activity จะยังคงอยู่คงที่ นั้นคือ activity จะยังคงอยู่ใน 3 state นี้ ในช่วง

เวลาระยะเวลาหนึ่ง ไม่เปลี่ยนไป state อื่นในทันที ได้แก่

Resumed

(แสดงอยู่ ทำงานอยู่)

ใน state นี้ activity จะแสดงอยู่ด้านหน้าสุด และผู้ใช้กำลังใช้งานอยู่ บอกครั้งจะเรียกว่า running state

Paused

(แสดงบางส่วน โดนบังไม่มิด)

ใน state นี้ activity จะถูกบดบังด้วย activity อื่น เช่น activity อื่น ที่อยู่ด้านหน้าสุดที่แสดงในลักษณะกึ่ง

โปรงใส หรือไม่ได้แสดงแบบเต็มหน้าจอ activity ในสถานะนี้จะไม่สามารถรับค่าจากผู้ใช้ และทำงานคำสั่งใดๆ ได้

Stopped

(แสดงแบบ background ผู้ใช้มองไม่เห็น)

ใน state นี้ activity จะถูกซ่อนอย่างสมบูรณ์และผู้ใช้มองไม่เห็น โดยจะถูกย้ายไปอยู่ด้านหลังในขณะที่อยู่ใน state นี้
ค่า activity instance และตัวแปรทั้งหมดจะยังคงอยู่ แต่จะไม่สามารถถูกเรียกใช้งานจาก code ใดๆ ได้

ในขณะที่ state อื่น เช่น Created และ Started จะแสดงชั่วคราว แล้วระบบก็จะเปลี่ยนไป state อื่น ในทันทีที่

method ถูกเรียกใช้งานอัตโนมัติ นั่นคือ หลังจากที่ระบบเรียกใช้งาน onCreate() แล้วก็จะเรียกใช้งาน onStart()
ทันที และสุดท้ายก็มาที่ onResumne() ซึ่งก็จะเข้าสู่ Resumed state

ทั้งหมดก็คือวัฏจักร activity เบื้อง้น ต่อไปเราจะได้เรียนรู้เกี่ยวกับการกำหนด การทำงานในวัฏจักร activity

การกำหนด Launcher Activity ใน app ของเรา

เมื่อผู้ใช้กดที่ icon app ของเราจากหน้า Home screen เพื่อใช้งาน ระบบก็จะเรียก onCreate() method

ขึ้นมาทำงานอัตโนมัติเพื่อที่จะเปิดใช้งาน activity ที่เราได้กำหนดให้เป็น activity หลัก ( “launcher” หรือ “main” )

ซึ่งก็จะเป็น activity ที่เป็นหน้าหลักที่ผู้ใช้จะเห็นเมื่อเข้ามาใช้งาน app

เราสามารถกำหนดได้ว่า activity ใด ที่จะใช้เป็น activity หลัก โดยกำหนดค่าในไฟล์ AndroidManifest.xml

activity หลักจะต้องกำหนด ค่าใน manifest ด้วย <intent-filter>

<intent-filter>
<action android:name=”android.intent.action.MAIN” />
<category android:name=”android.intent.category.LAUNCHER” />
</intent-filter>

โดยประกอบไปด้วย MAIN action

และ LAUNCHER category ดังตัวอย่างดังนี้

<activity android:name=”.MainActivity” android:label=”@string/app_name”>
<intent-filter>
<action android:name=”android.intent.action.MAIN” />
<category android:name=”android.intent.category.LAUNCHER” />
</intent-filter>
</activity>

ข้อสังเกต:: ใน android studio เมือ่เราสร้าง project android ขึ้นมา จะมีการประกาศค่าและกำหนด

ให้มีการเรียกใช้งาน filter นี้ในไฟล์ AndroidManifest.xml มาให้เรียบร้อยแล้ว

ถ้าไม่ได้กำหนด MAIN action และ LAUNCHER category แล้ว app icon ของเราจะไม่แสดงในหน้าหลักของ

ลิสรายการ app

การสร้าง Instance ใหม่

app ส่วนใหญ่จะประกอบไปด้วย activity หลายอันทำงานแตกต่างกันไป ไม่ว่าจะเป็น Activity หลัก ที่ถูก

สร้างขึ้นเมื่อผู้ใช้คลิกที่ icon app หรือ activity ต่างๆ ที่ถูกเรียกใช้งานโดยผู้ใช้ ทั้งหมดล้วนแล้วเป็นสิ่งที่ระบบ

สร้าง instance ใหม่ของ activity โดยการเรียกใช้ผ่าน onCreate() method

ต้องใช้ onCreate() method ในเหตุผลเพื่อเริ่มต้น application ซึ่งควรจะเกิดขึ้นเพียงครั้งเดียวตลอดหนึ่ง

วัฏจักรของ activity เช่นเราใช้ onCreate() กำหนดหน้าตาของ app หรือประกาศตัวแปรที่จะถูกใช้งานใน class เป็นต้น

ตัวอย่าง

การใช้งาน onCreate() method ตามตัวอย่างด้านล่าง แสดง code เพื่อให้เห็นการตั้งค่าเบื่องต้น

เช่น การกำหนด user interface (โดยใช้ XML layout ไฟล์) , การประกาศตัวแปรต่างๆ ,

การตั้งค่ากำหนดเงื่อนไข UI

package com.exmple.myfirstapp;

import android.app.ActionBar;
import android.content.Intent;
import android.os.Build;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.TextView;

public class MainActivity extends AppCompatActivity {

TextView mTextView; // การประกาศตัวแปรจำหรับ text view ใน layout

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

// การกำหนด user interface (โดยใช้ XML layout ไฟล์)
// ไฟล์ layout ใน project จะอยู่ที่ res/layout/main_activity.xml
setContentView(R.layout.main_activity);

// กำหนดค่าให้กับ TextView ดังนั้นเราสามารถเรียกใช้งานผ่านชื่อตัวแปรได้ภายหลัง
mTextView = (TextView) findViewById(R.id.text_message);

// ตั้งค่าสำหรับกำหนดเงื่อนไข UI
// ตรวจสอบเพื่อยืนยันว่าเรากำลังใช้งานบน android Honeycomb
// หรือสูงกว่า เพื่อเรียกใช้ ActionBar API
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
// กำหนดให้ icon ใน action bar ไม่ทำงานคล้ายปุ่ม Home
ActionBar actionBar = getActionBar();
actionBar.setHomeButtonEnabled(false);
}
}
}

มื่อ onCreate() ทำงานเสร็จ ระบบจะเรียก onStart() และ onResume() memthod มาทำงานต่อในทันที activity ของเราจะไม่อยู่ใน Created state หรือ Started state ในทางเทคนิค activity จะแสดงขึ้นมาทันทีที่ onStart() ถูกเรียกใช้งาน แต่ onResume() จะแสดงตามมาติดๆ ในทันทีและก็จะอยู่ใน Resumed state จนกว่าจะมีการเปลี่ยนแปลงบางอย่างเกิดขึ้น เช่น มีสายโทรเข้าหรือผู้ใช้เปิดไป activity อืน หรือปิดหน้าจอลง

ในบทเรียนต่อไป เราจะได้เห็นว่า method ที่เริ่มต้นอื่นๆ เช่น onStart() และ onResume() มีประโยชน์ในวัฏจักรของ

activity อย่างไรเมื่อกลับจาก Paused หรือ Stoped state มาที่ Resumed state

ข้อสังเกต:: ใน onCreate() method จะมี parameter ที่ชื่อ savedInstanceState ซึ่งเราจะได้มาดูกันต่อภายหลังในเรื่องเกี่ยวกับ
การสร้าง activity ขึ้นมาใหม่

โครงสร้างของวัฏจักร activity ที่เน้นไปที่ 3 method หลัก ที่ระบบเรียกใช้อัตโนมัติตามลำดับ เมื่อมีการสร้าง instance

ของ activity ขึ้นมาใหม่ ได้แก่ onCreate(), onStart() และ onResume() เมื่อลำดับการทำงานเสร็จสิ้นลง activity จะ

มาอยู่ที่ Resumed state ซึ่งผู้ใช้ใช้งานอยู่ จนกว่าจะเปลียนไปเรียกใช้งาน activity อื่นขึ้นมา

การสิ้นสุดการทำงานของ Activity (Destroy Activity)

ในขณะที่วัฏจักรของ activity มี method แรก คือ onCreate() และ method สุดท้ายคือ onDestroy()

ระบบจะเรียก method นี้ใน activity เป็นสัญญาณว่า activity instance นี้จะถูกลบบออกอย่างสมบูรณ์จาก

หน่วยความจำของระบบ (system memory)

app ส่วนใหญ่ ไม่จำเป็นต้องกำหนด method นี้ เพราะว่า local class ถูกทำลายไปพร้อมกับ activity

และ activity แทบจะถูกลบไปอย่่างสมบูร์ในระหว่างเรียกใช้งาน onPause() และ onStop() อย่างไรก็ตาม

ถ้า activity ของเรามีการกำหนดให้มีการทำงานแบบ background (อยู่เบื้องหลัง) ในขั้นตอน onCreate() ด้วยแล้ว

หรือ มีการใช้งานทรัพยากรของระบบเป็นระยะเวลานาน เป็นเหตุให้ความจำถูกใช้งานจำนวนมากหากไม่ทำการปิด

การใช้งาน จึงควรอย่างยิ่งที่จะเรียกใช้งาน method onDestroy() เพื่อคืนค่าหน่วยความจำให้ระบบ

@Override
public void onDestroy() {
super.onDestroy(); // เรียกใช้งาน superclass ทุกครั้งเสมอ

// หยุดการติดตามหรือตรวจจับ method ของ activity
android.os.Debug.stopMethodTracing();
}

ข้อสังเกต:: ระบบจะเรียกใช้งาน onDestroy() หลังจากเรียกใช้งาน onPause() และ onStop() แล้วในทุกเหตุการณ์ ยกเว้นกรณี
มีการกำหนดให้เรียกใช้ finish() ภายใน onCreate() method ในกรณีเช่น activity หยุดชั่วคราวเพื่อทำการเรียก

ใช้งาน activity อื่นข้ามา แล้วเราทำการกำหนดให้ มีการเรียกใช้งาน finish() ที่กำหนดใน onCreate() method เพื่อทำลาย

activity ในกรณีนี้ ระบบจะทำการเรียก onDestroy() ทันทีโดยไม่ผ่าน callback method อื่น เช่นไม่ผ่าน onPause() หรือ onStop() แบบนี้เป็นต้น

--

--