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

Cách truyền dữ liệu giữa các Fragment trong Android

Hướng dẫn này trình bày cách truyền dữ liệu giữa hai Fragment trong Android thông qua Interface callback. Đây là mẫu thiết kế phổ biến, tuân thủ nguyên tắc tách biệt mối quan hệ (loose coupling) - Fragment không biết trực tiếp về nhau mà giao tiếp qua Activity chứa.

Các bước thực hiện

Bước 1: Tạo dự án mới

Mở Android Studio, chọn File → New Project và điền thông tin cần thiết.

Bước 2: Layout Activity chính (res/layout/activity_main.xml)

<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:background="#574706"
    tools:context=".MainActivity">

    <fragment
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:name="app.com.sample.FragmentOne"
        android:id="@+id/fragment"
        android:layout_alignParentTop="true"
        android:layout_centerHorizontal="true"
        tools:layout="@layout/fragment_fragment_one" />

    <fragment
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:name="app.com.sample.FragmentTwo"
        android:id="@+id/fragment2"
        android:layout_below="@+id/fragment"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="41dp"
        tools:layout="@layout/fragment_fragment_two" />

</RelativeLayout>

Bước 3: MainActivity - Điều phối giao tiếp (src/MainActivity.java)

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;

public class MainActivity extends AppCompatActivity implements FragmentOne.OnFragmentInteractionListener {

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

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.menu_main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        int id = item.getItemId();
        if (id == R.id.textUpdate) {
            return true;
        }
        return super.onOptionsItemSelected(item);
    }

    // Implement interface từ FragmentOne
    @Override
    public void onFragmentInteraction(String userContent) {
        FragmentTwo fragmentTwo = (FragmentTwo) getSupportFragmentManager().findFragmentById(R.id.fragment2);
        fragmentTwo.updateTextField(userContent);
    }
}

Bước 4: Tạo hai Fragment

a) FragmentOne.java - Gửi dữ liệu

import android.app.Activity;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;

public class FragmentOne extends Fragment {
    private OnFragmentInteractionListener mListener;
    private EditText userInput;
    private String userData;

    public FragmentOne() {}

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_fragment_one, container, false);
        userInput = view.findViewById(R.id.userInput);
        Button update = view.findViewById(R.id.button);

        update.setOnClickListener(v -> {
            if (userInput.getText().toString().isEmpty()) {
                Toast.makeText(getActivity(), "Vui lòng nhập nội dung", Toast.LENGTH_LONG).show();
                return;
            }
            userData = userInput.getText().toString();
            onButtonPressed(userData);
        });
        return view;
    }

    public void onButtonPressed(String userContent) {
        if (mListener != null) {
            mListener.onFragmentInteraction(userContent);
        }
    }

    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);
        try {
            mListener = (OnFragmentInteractionListener) activity;
        } catch (ClassCastException e) {
            throw new ClassCastException(activity.toString() + " must implement OnFragmentInteractionListener");
        }
    }

    @Override
    public void onDetach() {
        super.onDetach();
        mListener = null;
    }

    public interface OnFragmentInteractionListener {
        void onFragmentInteraction(String userContent);
    }
}

Layout FragmentOne (fragment_fragment_one.xml)

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="https://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:padding="4dp"
    android:paddingBottom="32dp">

    <EditText
        android:id="@+id/userInput"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentTop="true"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="16dp"
        android:ems="10"
        android:inputType="text">
        <requestFocus />
    </EditText>

    <Button
        android:id="@+id/button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerHorizontal="true"
        android:layout_below="@id/userInput"
        android:layout_marginTop="20dp"
        android:padding="16dp"
        android:elevation="4dp"
        android:text="Cập nhật" />

</RelativeLayout>

b) FragmentTwo.java - Nhận và hiển thị dữ liệu

import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

public class FragmentTwo extends Fragment {
    private TextView updateText;

    public FragmentTwo() {}

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_fragment_two, container, false);
        updateText = view.findViewById(R.id.textUpdate);
        return view;
    }

    // Phương thức public để Activity gọi từ FragmentOne
    public void updateTextField(String newText) {
        updateText.setText(newText);
    }
}

Layout FragmentTwo (fragment_fragment_two.xml)

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

    <TextView
        android:id="@+id/textUpdate"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text=""
        android:textSize="24sp"
        android:layout_alignParentTop="true"
        android:layout_centerHorizontal="true"
        android:textStyle="bold"
        android:layout_marginTop="32dp" />

</RelativeLayout>

Bước 5: Cấu hình AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="https://schemas.android.com/apk/res/android"
    package="app.com.sample">
    <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. Nhập văn bản vào FragmentOne, nhấn "Cập nhật" - văn bản sẽ hiển thị ngay trên FragmentTwo.

Cách truyền dữ liệu giữa các Fragment trong Android Cách truyền dữ liệu giữa các Fragment trong Android

Giải thích cơ chế

  • FragmentOne định nghĩa interface OnFragmentInteractionListener
  • MainActivity implement interface này, đóng vai trò trung gian
  • Khi nút bấm trong FragmentOne được nhấn, nó gọi mListener.onFragmentInteraction()
  • MainActivity nhận dữ liệu, tìm FragmentTwo qua FragmentManager và gọi updateTextField()

Cách này đảm bảo FragmentOne và FragmentTwo hoàn toàn độc lập, dễ bảo trì và kiểm thử.