Intents và Navigation
1. Giới thiệu
Intent là cơ chế messaging để yêu cầu hành động từ component khác.
2. Loại Intent
Explicit Intent
Chỉ định rõ component đích:
// Mở Activity cụ thể
val intent = Intent(this, DetailActivity::class.java)
startActivity(intent)Implicit Intent
Khai báo action chung, hệ thống chọn component phù hợp:
// Mở URL
val intent = Intent(Intent.ACTION_VIEW, Uri.parse("https://google.com"))
startActivity(intent)3. Truyền dữ liệu
Primitives
val intent = Intent(this, DetailActivity::class.java).apply {
putExtra("id", 123)
putExtra("name", "Alice")
putExtra("active", true)
}
startActivity(intent)Nhận dữ liệu
class DetailActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val id = intent.getIntExtra("id", 0)
val name = intent.getStringExtra("name") ?: ""
val active = intent.getBooleanExtra("active", false)
}
}Parcelable Objects
@Parcelize
data class User(
val id: Int,
val name: String,
val email: String
) : Parcelable
// Gửi
intent.putExtra("user", user)
// Nhận
val user = intent.getParcelableExtra<User>("user")4. Implicit Intents phổ biến
Mở trình duyệt
val intent = Intent(Intent.ACTION_VIEW, Uri.parse("https://example.com"))
startActivity(intent)Gửi email
val intent = Intent(Intent.ACTION_SENDTO).apply {
data = Uri.parse("mailto:")
putExtra(Intent.EXTRA_EMAIL, arrayOf("[email protected]"))
putExtra(Intent.EXTRA_SUBJECT, "Subject")
putExtra(Intent.EXTRA_TEXT, "Email body")
}
if (intent.resolveActivity(packageManager) != null) {
startActivity(intent)
}Gọi điện
val intent = Intent(Intent.ACTION_DIAL).apply {
data = Uri.parse("tel:0123456789")
}
startActivity(intent)Chia sẻ
val intent = Intent(Intent.ACTION_SEND).apply {
type = "text/plain"
putExtra(Intent.EXTRA_TEXT, "Check this out!")
}
startActivity(Intent.createChooser(intent, "Share via"))Chụp ảnh
val intent = Intent(MediaStore.ACTION_IMAGE_CAPTURE)
if (intent.resolveActivity(packageManager) != null) {
startActivityForResult(intent, REQUEST_IMAGE_CAPTURE)
}5. Activity Result API (Modern)
class MainActivity : ComponentActivity() {
private val getContent = registerForActivityResult(
ActivityResultContracts.GetContent()
) { uri: Uri? ->
// Handle selected image URI
}
private val takePicture = registerForActivityResult(
ActivityResultContracts.TakePicturePreview()
) { bitmap: Bitmap? ->
// Handle captured image
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
Column {
Button(onClick = { getContent.launch("image/*") }) {
Text("Pick Image")
}
Button(onClick = { takePicture.launch(null) }) {
Text("Take Photo")
}
}
}
}
}6. Custom Activity Result
// Activity A
private val detailLauncher = registerForActivityResult(
ActivityResultContracts.StartActivityForResult()
) { result ->
if (result.resultCode == Activity.RESULT_OK) {
val data = result.data?.getStringExtra("result")
// Handle result
}
}
// Launch
detailLauncher.launch(Intent(this, DetailActivity::class.java))
// Activity B (DetailActivity)
setResult(Activity.RESULT_OK, Intent().apply {
putExtra("result", "Success")
})
finish()7. Navigation với Compose
Setup Navigation
@Composable
fun NavGraph() {
val navController = rememberNavController()
NavHost(navController, startDestination = "home") {
composable("home") {
HomeScreen(
onNavigateToDetail = { id ->
navController.navigate("detail/$id")
}
)
}
composable(
"detail/{id}",
arguments = listOf(navArgument("id") { type = NavType.IntType })
) { backStackEntry ->
val id = backStackEntry.arguments?.getInt("id") ?: 0
DetailScreen(id)
}
}
}Navigate với arguments
// Navigate
navController.navigate("detail/123")
// Navigate và pop current
navController.navigate("home") {
popUpTo("home") { inclusive = true }
}
// Go back
navController.popBackStack()8. Deep Links
Khai báo trong Manifest
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="myapp"
android:host="product" />
</intent-filter>
</activity>Trong Compose Navigation
composable(
"detail/{id}",
deepLinks = listOf(navDeepLink {
uriPattern = "myapp://product/{id}"
})
) { backStackEntry ->
DetailScreen(backStackEntry.arguments?.getInt("id") ?: 0)
}📝 Tóm tắt
| Loại | Mục đích |
|---|---|
| Explicit Intent | Mở component cụ thể |
| Implicit Intent | Yêu cầu action chung |
| putExtra/getExtra | Truyền dữ liệu |
| ActivityResultAPI | Nhận kết quả từ Activity |
| NavHost | Navigation trong Compose |
| Deep Links | Mở app từ URL |
Last updated on