Computer >> บทช่วยสอนคอมพิวเตอร์ >  >> การเขียนโปรแกรม >> Android

วิธีส่งข้อมูลระหว่าง Fragment ใน Android

ภาพรวม

ตัวอย่างนี้แสดงวิธีส่งข้อมูลจาก Fragment หนึ่งไปยังอีก Fragment หนึ่งผ่าน Activity โดยใช้ Interface (Callback Pattern) ซึ่งเป็นแนวทางปฏิบัติที่ดีที่สุด (Best Practice)

ขั้นตอนการสร้าง

ขั้นตอนที่ 1: สร้างโปรเจกต์ใหม่

เปิด Android Studio ไปที่ File → New Project และกรอกข้อมูลที่จำเป็น

ขั้นตอนที่ 2: Layout หลัก (res/layout/activity_main.xml)

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="https://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <LinearLayout
        android:id="@+id/linearlayout01"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"
        android:background="#ccc"
        android:orientation="vertical">
        
        <fragment
            android:name="com.example.myapplication.FirstFragment"
            android:id="@+id/frag_1"
            android:layout_width="match_parent"
            android:layout_height="match_parent" />
    </LinearLayout>

    <LinearLayout
        android:id="@+id/linearlayout02"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"
        android:background="#eee"
        android:orientation="vertical">
        
        <fragment
            android:name="com.example.myapplication.SecondFragment"
            android:id="@+id/frag_2"
            android:layout_width="match_parent"
            android:layout_height="match_parent" />
    </LinearLayout>

</LinearLayout>

ขั้นตอนที่ 3: สร้าง Interface (src/OnButtonPressListener.java)

package com.example.myapplication;

public interface OnButtonPressListener {
    void onButtonPressed(String message);
}

ขั้นตอนที่ 4: Activity หลัก (src/MainActivity.java)

package com.example.myapplication;

import android.os.Bundle;
import androidx.appcompat.app.AppCompatActivity;
import androidx.fragment.app.Fragment;

public class MainActivity extends AppCompatActivity implements OnButtonPressListener {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }

    @Override
    public void onButtonPressed(String message) {
        // หา Fragment ปลายทาง
        Fragment fragment = getSupportFragmentManager().findFragmentById(R.id.frag_2);
        if (fragment instanceof SecondFragment) {
            ((SecondFragment) fragment).onFragmentInteraction(message);
        }
    }
}

ขั้นตอนที่ 5: Fragment ต้นทาง (src/FirstFragment.java)

package com.example.myapplication;

import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;

public class FirstFragment extends Fragment {
    private OnButtonPressListener listener;

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment, container, false);
        TextView textView = view.findViewById(R.id.text);
        
        textView.setOnClickListener(v -> {
            if (listener != null) {
                listener.onButtonPressed("Message From First Fragment");
            }
        });
        return view;
    }

    @Override
    public void onAttach(@NonNull Context context) {
        super.onAttach(context);
        if (context instanceof OnButtonPressListener) {
            listener = (OnButtonPressListener) context;
        } else {
            throw new RuntimeException(context.toString() + " must implement OnButtonPressListener");
        }
    }

    @Override
    public void onDetach() {
        super.onDetach();
        listener = null; // ป้องกัน Memory Leak
    }
}

ขั้นตอนที่ 6: Fragment ปลายทาง (src/SecondFragment.java)

package com.example.myapplication;

import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;

public class SecondFragment extends Fragment {
    private TextView textView;

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment, container, false);
        textView = view.findViewById(R.id.text);
        return view;
    }

    public void onFragmentInteraction(String message) {
        Log.d("SecondFragment", "Received: " + message);
        if (textView != null) {
            textView.setText(message);
        }
    }
}

ขั้นตอนที่ 7: Layout สำหรับ Fragment (res/layout/fragment.xml)

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="https://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:gravity="center"
    android:layout_height="match_parent">
    <TextView
        android:id="@+id/text"
        android:textSize="30sp"
        android:text="Click"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />
</LinearLayout>

รูปแบบการสื่อสาร Fragment อื่นๆ

1. Shared ViewModel (แนะนำสำหรับ Architecture Modern)

// SharedViewModel.kt
class SharedViewModel : ViewModel() {
    val message = MutableLiveData<String>()
}

// FirstFragment
viewModel = ViewModelProvider(requireActivity()).get(SharedViewModel::class.java)
button.setOnClickListener { viewModel.message.value = "Hello" }

// SecondFragment
viewModel = ViewModelProvider(requireActivity()).get(SharedViewModel::class.java)
viewModel.message.observe(viewLifecycleOwner) { textView.text = it }

2. Fragment Result API (API ใหม่)

// Sender (FirstFragment)
setFragmentResult("requestKey", bundleOf("message" to "Hello"))

// Receiver (SecondFragment)
setFragmentResultListener("requestKey") { requestKey, bundle ->
    val message = bundle.getString("message")
}

3. Arguments (สำหรับข้อมูลเริ่มต้น)

// ส่งข้อมูลตอนสร้าง Fragment
val fragment = SecondFragment().apply {
    arguments = bundleOf("key" to "value")
}

// รับใน Fragment
val value = arguments?.getString("key")

สรุปแนวทางเลือก

วิธีเหมาะสำหรับข้อดี
Interface/CallbackSimple communication, Legacyเข้าใจง่าย ควบคุมได้ชัดเจน
Shared ViewModelModern apps, Lifecycle-awareSurvives config change, Testable
Fragment Result APIOne-time results, Request/ResponseType-safe, Lifecycle-aware
ArgumentsInitial dataSimple, Standard