Giới thiệu
Ví dụ minh họa cách đưa một Activity đã tồn tại trong back stack lên trên cùng (foreground) thay vì tạo instance mới, sử dụng flag Intent.FLAG_ACTIVITY_REORDER_TO_FRONT trong Kotlin.
Các bước thực hiện
Bước 1: Tạo dự án mới
Android Studio > File > New Project.
Bước 2: Layout MainActivity (activity_main.xml)
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="https://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="4dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_marginTop="70dp"
android:background="#008080"
android:padding="5dp"
android:text="TutorialsPoint"
android:textColor="#fff"
android:textSize="24sp"
android:textStyle="bold" />
</RelativeLayout>
Bước 3: MainActivity.kt - Khởi động NewActivity với flag
import android.content.Intent
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
title = "KotlinApp"
val intent = Intent(this, NewActivity::class.java).apply {
// Flag quan trọng: Đưa activity đã có trong stack lên top
flags = Intent.FLAG_ACTIVITY_REORDER_TO_FRONT
}
startActivity(intent)
}
}
Bước 4: Tạo NewActivity (Empty Activity)
Chuột phải package > New > Activity > Empty Activity > Name: NewActivity.
NewActivity.kt
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
class NewActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_new)
title = "KotlinApp"
}
}
activity_new.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="https://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="4dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_marginTop="70dp"
android:background="#008080"
android:padding="5dp"
android:text="TutorialsPoint"
android:textColor="#fff"
android:textSize="24sp"
android:textStyle="bold" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:text="New Activity"
android:textAlignment="center"
android:textColor="@android:color/holo_blue_dark"
android:textSize="24sp"
android:textStyle="bold" />
</RelativeLayout>
Bước 5: AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="https://schemas.android.com/apk/res/android"
package="com.example.reorderfront">
<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">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".NewActivity" />
</application>
</manifest>
Chạy và kiểm tra
- Chạy app -> MainActivity hiện ra -> Tự động start NewActivity (do code trong onCreate).
- Nhấn Back -> Quay về MainActivity.
- Nhấn nút Home (về launcher).
- Mở app lại từ launcher -> MainActivity onCreate chạy lại -> startActivity(NewActivity) với FLAG_REORDER_TO_FRONT.
- Kết quả: NewActivity cũ (đã pause) được đưa lên top, KHÔNG tạo instance mới. Trạng thái của NewActivity được giữ nguyên.
Các Flag Intent liên quan đến Task/Stack
| Flag | Hành vi |
|---|---|
FLAG_ACTIVITY_REORDER_TO_FRONT | Nếu activity đã có trong task, đưa lên top. Không tạo mới. |
FLAG_ACTIVITY_CLEAR_TOP | Nếu activity đã có, xóa tất cả activity trên nó và deliver intent đến onNewIntent(). |
FLAG_ACTIVITY_SINGLE_TOP | Nếu activity đã ở top, không tạo mới, gọi onNewIntent(). |
FLAG_ACTIVITY_NEW_TASK | Khởi động trong task mới (dùng cho Notification, Widget). |
FLAG_ACTIVITY_CLEAR_TASK | Xóa task hiện tại, activity mới thành root (dùng với NEW_TASK). |
FLAG_ACTIVITY_NO_HISTORY | Activity không vào back stack (finish khi rời). |
launchMode trong Manifest (Thay thế flag)
Có thể khai báo trong <activity> tag:
<activity
android:name=".NewActivity"
android:launchMode="singleTop" /> <!-- Tương đương SINGLE_TOP -->
<activity
android:name=".NewActivity"
android:launchMode="singleTask" /> <!-- Tương đương CLEAR_TOP + NEW_TASK -->
<activity
android:name=".NewActivity"
android:launchMode="singleInstance" /> <!-- Chỉ 1 instance trong toàn hệ thống -->
singleTop: Giống SINGLE_TOP flag.singleTask: Giống CLEAR_TOP + NEW_TASK. Activity thành root của task riêng.singleInstance: Giống singleTask nhưng không cho activity khác vào task đó.
Khi nào dùng FLAG_ACTIVITY_REORDER_TO_FRONT?
- Muốn giữ trạng thái Activity cũ (không destroy/create).
- Không muốn xóa các Activity khác trong stack (khác CLEAR_TOP).
- Ví dụ: Từ Notification click mở ChatActivity đã mở sẵn -> đưa nó lên top.