Giới thiệu
Hướng dẫn này trình bày cách Fragment gọi phương thức (method) của Activity chứa nó trong Android sử dụng Kotlin. Đây là pattern giao tiếp Fragment ↔ Activity phổ biến.
Các bước thực hiện
Bước 1: Tạo dự án mới
Tạo project: File → New Project.
Bước 2: Thiết kế giao diện Activity (res/layout/activity_main.xml)
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="https://schemas.android.com/apk/res/android"
xmlns:tools="https://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="8dp"
tools:context=".MainActivity">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_marginTop="50dp"
android:text="Tutorials Point"
android:textAlignment="center"
android:textColor="@android:color/holo_green_dark"
android:textSize="32sp"
android:textStyle="bold" />
<FrameLayout
android:id="@+id/frameLayout"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</RelativeLayout>
Bước 3: MainActivity.kt
import android.os.Bundle
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
title = "KotlinApp"
// Thêm Fragment vào FrameLayout
supportFragmentManager.beginTransaction()
.replace(R.id.frameLayout, SampleFragment())
.commit()
}
// Phương thức được Fragment gọi
fun fragmentMethod() {
Toast.makeText(this, "Method called From Fragment", Toast.LENGTH_LONG).show()
}
}
Bước 4: Tạo Fragment
Layout Fragment (res/layout/fragment_sample.xml)
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="https://schemas.android.com/apk/res/android"
xmlns:tools="https://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".SampleFragment">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:text="Calling a simple method from Fragment"
android:textAlignment="center"
android:textColor="@android:color/background_dark"
android:textSize="24sp"
android:textStyle="bold" />
</RelativeLayout>
SampleFragment.kt
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
class SampleFragment : Fragment() {
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
val view = inflater.inflate(R.layout.fragment_sample, container, false)
// Gọi method của Activity
(activity as? MainActivity)?.fragmentMethod()
return view
}
}
Bước 5: Cấu hình Manifest (androidManifest.xml)
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="https://schemas.android.com/apk/res/android"
package="app.com.q11">
<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>
</application>
</manifest>
Chạy ứng dụng
Kết nối thiết bị, nhấn Run. Fragment được load, gọi method của Activity hiển thị Toast "Method called From Fragment".
Các cách giao tiếp Fragment ↔ Activity
1. Ép kiểu Activity (Cách trên) - Đơn giản nhưng tight coupling
(activity as MainActivity).fragmentMethod()
2. Interface Callback (Khuyên dùng) - Loose coupling
// Interface
interface OnFragmentInteractionListener {
fun onFragmentAction(data: String)
}
// Activity implements
class MainActivity : AppCompatActivity(), OnFragmentInteractionListener {
override fun onFragmentAction(data: String) {
// Xử lý
}
}
// Fragment
class SampleFragment : Fragment() {
private var listener: OnFragmentInteractionListener? = null
override fun onAttach(context: Context) {
super.onAttach(context)
if (context is OnFragmentInteractionListener) {
listener = context
} else {
throw RuntimeException("$context must implement OnFragmentInteractionListener")
}
}
override fun onDetach() {
super.onDetach()
listener = null
}
private fun callActivity() {
listener?.onFragmentAction("Data from fragment")
}
}
3. Shared ViewModel (Modern, Best Practice)
// SharedViewModel.kt
class SharedViewModel : ViewModel() {
val actionLiveData = MutableLiveData()
}
// Activity
val viewModel = ViewModelProvider(this).get(SharedViewModel::class.java)
viewModel.actionLiveData.observe(this) { data ->
// Xử lý
}
// Fragment
val viewModel = ViewModelProvider(requireActivity()).get(SharedViewModel::class.java)
viewModel.actionLiveData.postValue("Data from fragment")
4. Fragment Result API (API 33+ / AndroidX Fragment 1.3+)
// Fragment gửi kết quả
setFragmentResult("requestKey", bundleOf("data" to "value"))
// Activity/Fragments khác lắng nghe
setFragmentResultListener("requestKey") { requestKey, bundle ->
val data = bundle.getString("data")
}
Kết luận
Cách ép kiểu Activity đơn giản nhưng tạo dependency cứng. Nên ưu tiên Interface hoặc Shared ViewModel để code dễ test, tái sử dụng và tuân thủ Clean Architecture.