Skip to Content

Activity

1. Giới thiệu

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ó.

💡

Activity là gì? Activity là một màn hình đơn lẻ với giao diện người dùng. Một ứng dụng email có thể có một activity hiển thị danh sách email mới, một activity khác để soạn email, và một activity khác để đọc email.

2. Khái niệm về Activity

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 chính của Activity

Đặc điểmMô tả
WindowActivity cung cấp cửa sổ để ứng dụng vẽ UI
Full-screenThường chiếm toàn bộ màn hình, nhưng có thể nhỏ hơn (floating windows)
Multi-windowCó thể hiển thị trong chế độ đa cửa sổ
One screenThô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

3. Activity Stack

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.

4 trạng thái của Activity

Trạng tháiMô tả
Active/RunningActivity ở 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.
VisibleActivity đã 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/HiddenActivity 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ớ.
DestroyedHệ 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.

4. Khai báo Activity trong Manifest

Để ứ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.

Khai báo cơ bản

<manifest ... > <application ... > <activity android:name=".ExampleActivity" /> ... </application ... > ... </manifest >
⚠️

Không thay đổi tên activity sau khi publish app! Nếu bạn làm vậy, một số chức năng có thể bị hỏng, chẳng hạn như app shortcuts.

Khai báo Main Activity

<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>

Khai báo Intent Filters

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>

Khai báo Permissions

<!-- Activity yêu cầu permission để được gọi --> <activity android:name=".ShareActivity" android:permission="com.myapp.permission.SHARE_POST" />

5. Tạo Activity cơ bản

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 ) }

Với XML Views (Legacy)

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!" } }

6. Ba Vòng đời quan trọng

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

Entire Lifetime

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 }

Visible Lifetime

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 }

Foreground Lifetime

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 }

7. Khởi động Activity khác

Sử dụng Intent

// Explicit Intent val intent = Intent(this, DetailActivity::class.java).apply { putExtra("user_id", 123) putExtra("user_name", "Alice") } startActivity(intent)

Nhận dữ liệu

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) } } }

Implicit Intent

val sendIntent = Intent().apply { action = Intent.ACTION_SEND type = "text/plain" putExtra(Intent.EXTRA_TEXT, textMessage) } startActivity(sendIntent)

8. Kết thúc Activity

// 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()

9. Launch Modes

<!-- 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" ... />

10. Activity với ViewModel

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 ) } } }
💡

ViewModel survive qua configuration changes (như xoay màn hình), trong khi Activity bị destroy và recreate. Vì vậy, hãy đặt UI data trong ViewModel thay vì Activity.


📝 Tóm tắt

Khái niệmMô tả
ActivityThành phần UI cơ bản, đại diện cho một màn hình
Entry PointActivity là điểm vào cho tương tác với người dùng
Activity StackCác activity được quản lý trong stack (LIFO)
4 StatesActive, Visible, Stopped, Destroyed
ManifestActivity phải được khai báo trong AndroidManifest.xml
Intent FiltersCho phép activity respond với implicit intents

📚 Tham khảo:

Last updated on