Bỏ qua để đến nội dung

Activity

Lớp Activity là một thành phần quan trọng của ứng dụng Android, và cách các activity được khởi chạy và kết hợp với nhau là một phần cơ bản trong mô hình ứng dụng của nền tảng Android. Khác với các mô hình lập trình khác nơi ứng dụng được khởi chạy bằng phương thức main(), hệ thống Android khởi tạo code trong một instance của Activity bằng cách gọi các callback methods tương ứng với các giai đoạn cụ thể trong vòng đời của nó.

Trải nghiệm ứng dụng di động khác với desktop ở chỗ tương tác của người dùng với ứng dụng không phải lúc nào cũng bắt đầu từ cùng một nơi. Thay vào đó, hành trình của người dùng thường bắt đầu một cách không xác định. Ví dụ:

  • Nếu bạn mở ứng dụng email từ màn hình chính, bạn có thể thấy danh sách email
  • Nếu bạn đang sử dụng ứng dụng mạng xã hội và nó khởi động ứng dụng email, bạn có thể đi thẳng đến màn hình soạn email

Lớp Activity được thiết kế để hỗ trợ mô hình này. Khi một ứng dụng gọi ứng dụng khác, ứng dụng gọi sẽ gọi một activity trong ứng dụng kia, thay vì toàn bộ ứng dụng. Theo cách này, activity đóng vai trò là điểm vào (entry point) cho tương tác của ứng dụng với người dùng.

Đặc điểm Mô tả
Window Activity cung cấp cửa sổ để ứng dụng vẽ UI
Full-screen Thường chiếm toàn bộ màn hình, nhưng có thể nhỏ hơn (floating windows)
Multi-window Có thể hiển thị trong chế độ đa cửa sổ
One screen Thông thường, một activity triển khai một màn hình trong ứng dụng
public class Activity
extends ContextThemeWrapper
implements ComponentCallbacks2, KeyEvent.Callback,
LayoutInflater.Factory2, View.OnCreateContextMenuListener,
Window.Callback

Các activity trong hệ thống được quản lý như activity stacks. Khi một activity mới được khởi chạy, nó thường được đặt lên trên cùng của stack hiện tại và trở thành running activity — activity trước đó luôn nằm bên dưới trong stack và sẽ không quay lại foreground cho đến khi activity mới kết thúc.

flowchart LR
A["🟢 Active/Running"] --> B["🟡 Visible"]
B --> C["🔴 Stopped/Hidden"]
C --> D["⚫ Destroyed"]
style A fill:#4CAF50,stroke:#2E7D32,color:#fff
style B fill:#FFC107,stroke:#FFA000,color:#000
style C fill:#f44336,stroke:#c62828,color:#fff
style D fill:#424242,stroke:#212121,color:#fff
Trạng thái Mô tả
Active/Running Activity ở foreground của màn hình (vị trí cao nhất của stack). Đây là activity mà người dùng đang tương tác.
Visible Activity đã mất focus nhưng vẫn hiển thị với người dùng. Điều này xảy ra khi một activity không full-screen hoặc trong suốt nằm trên activity của bạn.
Stopped/Hidden Activity bị che hoàn toàn bởi activity khác. Nó vẫn giữ tất cả state và thông tin, nhưng không còn hiển thị cho người dùng và thường bị hệ thống kill khi cần bộ nhớ.
Destroyed Hệ thống có thể huỷ activity khỏi bộ nhớ bằng cách yêu cầu nó finish, hoặc đơn giản là kill process của nó. Khi hiển thị lại cho người dùng, activity phải được khởi động lại hoàn toàn.

Để ứng dụng có thể sử dụng activity, bạn phải khai báo activity và một số thuộc tính của nó trong AndroidManifest.xml.

<manifest ... >
<application ... >
<activity android:name=".ExampleActivity" />
...
</application ... >
...
</manifest >
<activity
android:name=".MainActivity"
android:exported="true"
android:label="@string/app_name"
android:theme="@style/Theme.MyApp">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>

Intent filters cho phép khởi chạy activity dựa trên cả yêu cầu explicit lẫn implicit:

  • Explicit: “Khởi động activity Send Email trong ứng dụng Gmail”
  • Implicit: “Khởi động màn hình Send Email trong bất kỳ activity nào có thể thực hiện công việc này”
<activity android:name=".ExampleActivity" android:icon="@drawable/app_icon">
<intent-filter>
<action android:name="android.intent.action.SEND" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="text/plain" />
</intent-filter>
</activity>
<!-- Activity yêu cầu permission để được gọi -->
<activity
android:name=".ShareActivity"
android:permission="com.myapp.permission.SHARE_POST" />
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
MyAppTheme {
Surface(
modifier = Modifier.fillMaxSize(),
color = MaterialTheme.colorScheme.background
) {
Greeting("Android")
}
}
}
}
}
@Composable
fun Greeting(name: String, modifier: Modifier = Modifier) {
Text(
text = "Hello, $name!",
modifier = modifier
)
}
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
// Sử dụng findViewById để lấy views
val textView = findViewById<TextView>(R.id.textView)
textView.text = "Hello, Android!"
}
}

Activity có 3 key loops bạn cần quan tâm:

Xảy ra giữa lần gọi đầu tiên onCreate() đến lần gọi cuối cùng onDestroy().

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// Setup "global" state, tạo background thread
}
override fun onDestroy() {
super.onDestroy()
// Release tất cả resources
}

Xảy ra giữa onStart()onStop(). Trong thời gian này, người dùng có thể thấy activity trên màn hình.

override fun onStart() {
super.onStart()
// Register BroadcastReceiver để monitor UI changes
}
override fun onStop() {
super.onStop()
// Unregister BroadcastReceiver
}

Xảy ra giữa onResume()onPause(). Trong thời gian này, activity đang visible, active và tương tác với người dùng.

override fun onResume() {
super.onResume()
// Activity đang tương tác với user
}
override fun onPause() {
super.onPause()
// Pause operations, nhưng code nên lightweight
}
// Explicit Intent
val intent = Intent(this, DetailActivity::class.java).apply {
putExtra("user_id", 123)
putExtra("user_name", "Alice")
}
startActivity(intent)
class DetailActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val userId = intent.getIntExtra("user_id", 0)
val userName = intent.getStringExtra("user_name") ?: ""
setContent {
DetailScreen(userId, userName)
}
}
}
val sendIntent = Intent().apply {
action = Intent.ACTION_SEND
type = "text/plain"
putExtra(Intent.EXTRA_TEXT, textMessage)
}
startActivity(sendIntent)
// Kết thúc Activity hiện tại
finish()
// Kết thúc và xóa toàn bộ task stack
finishAffinity()
// Kết thúc với result
setResult(Activity.RESULT_OK, Intent().apply {
putExtra("result", "Success")
})
finish()
<!-- standard: Mặc định, Activity mới được thêm vào stack -->
<activity android:launchMode="standard" ... />
<!-- singleTop: Tái sử dụng nếu đã ở top của stack -->
<activity android:launchMode="singleTop" ... />
<!-- singleTask: Một instance duy nhất trong task -->
<activity android:launchMode="singleTask" ... />
<!-- singleInstance: Task riêng biệt, instance duy nhất -->
<activity android:launchMode="singleInstance" ... />
class MainActivity : ComponentActivity() {
private val viewModel: MainViewModel by viewModels()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
val uiState by viewModel.uiState.collectAsState()
MainScreen(
state = uiState,
onEvent = viewModel::onEvent
)
}
}
}

Khái niệm Mô tả
Activity Thành phần UI cơ bản, đại diện cho một màn hình
Entry Point Activity là điểm vào cho tương tác với người dùng
Activity Stack Các activity được quản lý trong stack (LIFO)
4 States Active, Visible, Stopped, Destroyed
Manifest Activity phải được khai báo trong AndroidManifest.xml
Intent Filters Cho phép activity respond với implicit intents

📚 Tham khảo: