Android Studio - Bundle 不在 Fragment 之间传递数据

Android Studio - Bundle not passing data between Fragments

我正在开发一个应用程序,该应用程序总共包含 5 个片段,并与底部导航菜单相关联。为了简单起见,我将使用其中的两个作为示例。

package com.example.ssresilience;

import android.annotation.SuppressLint;
import android.content.Intent;
import android.os.Bundle;

import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentTransaction;

import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;

/**
 * A simple {@link Fragment} subclass.
 * Use the {@link GoalsFragment#newInstance} factory method to
 * create an instance of this fragment.
 */
public class GoalsFragment extends Fragment {

    // TODO: Rename parameter arguments, choose names that match
    // the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
    private static final String ARG_PARAM1 = "param1";
    private static final String ARG_PARAM2 = "param2";

    // TODO: Rename and change types of parameters
    private String mParam1;
    private String mParam2;

    private Button fg_goals_socialize;
    private Button fg_goals_study;
    private Button fg_goals_exercise;
    private Button fg_goals_setgoal;
    private TextView fg_goals_placeholder;

    private int check = 0;

    public GoalsFragment() {
        // Required empty public constructor
    }

    /**
     * Use this factory method to create a new instance of
     * this fragment using the provided parameters.
     *
     * @param param1 Parameter 1.
     * @param param2 Parameter 2.
     * @return A new instance of fragment GoalsFragment.
     */
    // TODO: Rename and change types and number of parameters
    public static GoalsFragment newInstance(String param1, String param2) {
        GoalsFragment fragment = new GoalsFragment();
        Bundle args = new Bundle();
        args.putString(ARG_PARAM1, param1);
        args.putString(ARG_PARAM2, param2);
        fragment.setArguments(args);
        return fragment;
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if (getArguments() != null) {
            mParam1 = getArguments().getString(ARG_PARAM1);
            mParam2 = getArguments().getString(ARG_PARAM2);
        }
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        // Inflate the layout for this fragment
        View rootView = inflater.inflate((R.layout.fragment_goals), container, false);

        fg_goals_socialize = (Button)rootView.findViewById(R.id.fg_goals_socialize);
        fg_goals_socialize.setOnClickListener(this::onClick);
        fg_goals_study = (Button)rootView.findViewById(R.id.fg_goals_study);
        fg_goals_study.setOnClickListener(this::onClick);
        fg_goals_exercise = (Button)rootView.findViewById(R.id.fg_goals_exercise);
        fg_goals_exercise.setOnClickListener(this::onClick);
        fg_goals_setgoal = (Button)rootView.findViewById(R.id.fg_goals_setgoal);
        fg_goals_setgoal.setOnClickListener(this::onClick);
        fg_goals_placeholder = (TextView)rootView.findViewById(R.id.fg_goals_placeholder);

        return rootView;
    }

    @SuppressLint({"UseCompatLoadingForDrawables", "ResourceAsColor", "UseCompatLoadingForColorStateLists", "NonConstantResourceId", "SetTextI18n"})
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.fg_goals_socialize:
                fg_goals_placeholder.setText("• Talk to 3 or more people, other than your family.\n\n" +
                        "• Engage in phone or video calls from any device.\n\n" +
                        "• Exit your house for more than 2 hours.\n\n" +
                        "• Meet new people online or via your phone.");
                fg_goals_socialize.setBackgroundDrawable(getResources().getDrawable(R.drawable.buttoncolor_rect));
                fg_goals_socialize.setTextColor(getResources().getColorStateList(R.color.buttoncolor_text));
                fg_goals_study.setBackgroundDrawable(getResources().getDrawable(R.drawable.buttoncolor_rect_reset));
                fg_goals_study.setTextColor(getResources().getColorStateList(R.color.buttoncolor_text_reset));
                fg_goals_exercise.setBackgroundDrawable(getResources().getDrawable(R.drawable.buttoncolor_rect_reset));
                fg_goals_exercise.setTextColor(getResources().getColorStateList(R.color.buttoncolor_text_reset));
                check = 1;
                break;
            case R.id.fg_goals_study:
                fg_goals_placeholder.setText("• Study for 1 or more hours today.\n\n" +
                        "• Work for at least 1 hour on your projects.\n\n" +
                        "• Talk to friends or relatives about your projects.\n\n" +
                        "• Dedicate study time for the course of your liking.");
                fg_goals_socialize.setBackgroundDrawable(getResources().getDrawable(R.drawable.buttoncolor_rect_reset));
                fg_goals_socialize.setTextColor(getResources().getColorStateList(R.color.buttoncolor_text_reset));
                fg_goals_study.setBackgroundDrawable(getResources().getDrawable(R.drawable.buttoncolor_rect));
                fg_goals_study.setTextColor(getResources().getColorStateList(R.color.buttoncolor_text));
                fg_goals_exercise.setBackgroundDrawable(getResources().getDrawable(R.drawable.buttoncolor_rect_reset));
                fg_goals_exercise.setTextColor(getResources().getColorStateList(R.color.buttoncolor_text_reset));
                check = 2;
                break;
            case R.id.fg_goals_exercise:
                fg_goals_placeholder.setText("• Dedicate more than 1 hour on physical exercise.\n\n" +
                        "• Participate in physical exercises with friends or others.\n\n" +
                        "• Achieve your physical exercise-related goal.\n\n" +
                        "• Track your fitness-related progress in any way.");
                fg_goals_socialize.setBackgroundDrawable(getResources().getDrawable(R.drawable.buttoncolor_rect_reset));
                fg_goals_socialize.setTextColor(getResources().getColorStateList(R.color.buttoncolor_text_reset));
                fg_goals_study.setBackgroundDrawable(getResources().getDrawable(R.drawable.buttoncolor_rect_reset));
                fg_goals_study.setTextColor(getResources().getColorStateList(R.color.buttoncolor_text_reset));
                fg_goals_exercise.setBackgroundDrawable(getResources().getDrawable(R.drawable.buttoncolor_rect));
                fg_goals_exercise.setTextColor(getResources().getColorStateList(R.color.buttoncolor_text));
                check = 3;
                break;
            default:
                break;
        }
        switch (v.getId()) {
            case R.id.fg_goals_setgoal:
                if(check == 0) {
                    Toast.makeText(getActivity(), "Please select one of the 3 Goals!",
                            Toast.LENGTH_LONG).show();
                }
                if(check == 1) {
                    Bundle args = new Bundle();
                    args.putInt("goal", 1);
                    ProgressFragment newFragment = new ProgressFragment();
                    newFragment.setArguments(args);
                    Toast.makeText(getActivity(), "Current Goal: Socialize More",
                            Toast.LENGTH_LONG).show();
                }
                if(check == 2) {
                    Bundle args = new Bundle();
                    args.putInt("goal", 2);
                    ProgressFragment newFragment = new ProgressFragment();
                    newFragment.setArguments(args);
                    Toast.makeText(getActivity(), "Current Goal: Enhance Study Motives",
                            Toast.LENGTH_LONG).show();
                }
                if(check == 3) {
                    Bundle args = new Bundle();
                    args.putInt("goal", 3);
                    ProgressFragment newFragment = new ProgressFragment();
                    newFragment.setArguments(args);
                    Toast.makeText(getActivity(), "Current Goal: Physical Exercise",
                            Toast.LENGTH_LONG).show();
                }
                break;
            default:
                break;
        }
    }
}

在上面的 GoalsFragment.java 中,有 2 个 switch 方法,一个突出显示按钮并分配 check 变量,而下面的另一个包含确定按下哪个按钮的 if 语句。这 2 个工作正常,所以问题不存在。根据按下的按钮,在第二个 switch 方法中,我们有 3 个不同的 bundles,用于将数据传递给 Fragment ProgressFragment.java,当按下“设置目标”按钮时。

package com.example.ssresilience;

import android.os.Bundle;

import androidx.fragment.app.Fragment;

import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import android.widget.Toast;

/**
 * A simple {@link Fragment} subclass.
 * Use the {@link ProgressFragment#newInstance} factory method to
 * create an instance of this fragment.
 */
public class ProgressFragment extends Fragment {

    // TODO: Rename parameter arguments, choose names that match
    // the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
    private static final String ARG_PARAM1 = "param1";
    private static final String ARG_PARAM2 = "param2";

    // TODO: Rename and change types of parameters
    private String mParam1;
    private String mParam2;

    public ProgressFragment() {
        // Required empty public constructor
    }

    /**
     * Use this factory method to create a new instance of
     * this fragment using the provided parameters.
     *
     * @param param1 Parameter 1.
     * @param param2 Parameter 2.
     * @return A new instance of fragment ProgressFragment.
     */
    // TODO: Rename and change types and number of parameters
    public static ProgressFragment newInstance(String param1, String param2) {
        ProgressFragment fragment = new ProgressFragment();
        Bundle args = new Bundle();
        args.putString(ARG_PARAM1, param1);
        args.putString(ARG_PARAM2, param2);
        fragment.setArguments(args);
        return fragment;
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if (getArguments() != null) {
            mParam1 = getArguments().getString(ARG_PARAM1);
            mParam2 = getArguments().getString(ARG_PARAM2);
        }
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        // Inflate the layout for this fragment
        View rootView = inflater.inflate(R.layout.fragment_progress, container, false);

        // Get the Selected Goal data from the GoalsFragment
        Bundle b = getArguments();
        int goal = b.getInt("goal");
        System.out.println(goal);

        // Set the Progress Fragment Text according to the selected Goal
        TextView fg_progress_header2 = (TextView) rootView.findViewById(R.id.fg_progress_header2);
        if (goal == 1) {
            fg_progress_header2.setText("Socialize More");
        } if (goal == 2) {
            fg_progress_header2.setText("Enhance Study Motives");
        } if (goal == 3) {
            fg_progress_header2.setText("Physical Exercise");
        }

        return rootView;
    }
}

在第二个片段中,我试图从 中的 3 个 bundles 之一中检索 goal 数据GoalsFragment.java,并相应地设置 TextViews 的文本。出于测试目的,我添加了一个 System.out.println(goal);,其中 returns 0,表示未从第一个片段中正确检索到包数据。

我什至尝试将 bundle 放在 GoalsFragment.javaonCreateView 方法中,以防万一下面的错误代码,但它仍然没有工作。

有人能帮帮我吗?我所做的一切似乎都没有用...

提前致谢!

您需要通过 ViewModel 或片段侦听器与多个片段通信

来自你的GoalFragment

    Bundle result = new Bundle();
    result.putInt("goal", 1);
    getParentFragmentManager().setFragmentResult("progress", result);

在你的ProgressFragment

@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    getParentFragmentManager().setFragmentResultListener("requestKey", this, new FragmentResultListener() {
        @Override
        public void onFragmentResult(@NonNull String requestKey, @NonNull Bundle bundle) {
            // We use a String here, but any type that can be put in a Bundle is supported
            String result = bundle.getInt("goal");
            // Do something with the result
        }
    });
}

具体实现可以看文档 https://developer.android.com/guide/fragments/communicate#java