Computer >> Hướng Dẫn Máy Tính >  >> Lập Trình >> Android

Cách gọi phương thức Activity từ Fragment trong Android bằng Kotlin

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.