在同一个Activity中的Fragment之间传递数据

9
我正在一个包含多个片段的活动项目中工作。现在我需要在这些片段之间共享一些数据(整数、字符串、arraylist)。
第一次我使用了静态字段,但我认为这是一种不好的方式,然后我找到这个解决方案
但在我的情况下,没有按钮可以点击,我只需要在片段之间导航,有没有简单的方法在片段之间共享数据?

如果您只是查看数据而没有任何用户交互(没有按钮可点击,列表视图选择要进行...),为什么需要将数据从只读片段传递到其他片段? - k3b
在第一个片段中,我进行了许多处理;其他片段中也需要相同的处理,因此我不想重复它们以减少复杂性和时间使用。 - Soufiane
7个回答

8

我认为对于你来说最好的解决方案是将变量放在主活动中,并从片段中访问它们。我的意思是,如果你必须在所有片段中执行相同的操作,那么可以在活动中编写代码,只需调用所需的方法即可。

你需要使用接口来实现这个目的。

public interface DataCommunication {
    public String getMyVariableX();
    public void setMyVariableX(String x);
    public int getMyVariableY();
    public void setMyVariableY(int y);
}

然后,在你的活动中实现它。
public class MainActivity extends Activity implements DataCommunication {

    private String x;
    private int y;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        ...   
    }

    ...

    @Override
    public String getMyVariableX(){
        return x;
    }

    @Override
    public void setMyVariableX(String x){
        //do whatever or just set
        this.x = x;
    }

    @Override
    public int getMyVariableY(){
        return y;
    }

    @Override
    public void setMyVariableY(int y){
        //do whatever or just set
        this.y = y;
    }

    ...

然后,在所有的片段中添加该活动:

public class Fragment_1 extends Fragment{

    DataCommunication mCallback;

 @Override
    public void onAttach(Context context) {
        super.onAttach(context);

        // This makes sure that the container activity has implemented
        // the callback interface. If not, it throws an exception
        try {
            mCallback = (DataCommunication) context;
        } catch (ClassCastException e) {
            throw new ClassCastException(context.toString()
                    + " must implement DataCommunication");
        }
    }

    ...

最后,当你需要在片段内使用一个变量时,只需使用你创建的 get 和 set 方法。
来源:https://developer.android.com/training/basics/fragments/communicating.html

1
委托模式,最佳想法 - Luca Nicoletti
对我来说不起作用,我有一个空值或者添加片段到viewPager Adapter的问题。 - Soufiane
@Soufiane,请解释一下你的意思。这个答案提供了一个非常好的解决方案,现在你需要根据自己的要求进行修改,比如在getter或setter中添加空值检查。 - Sufian
1
干得好!但是onAttach(Activity)现在已经被弃用了,也许你可以编辑一下你的好答案。 - basti12354

7
最简单的方法是使用Bundle。您可以按照以下步骤操作:

Fragment A:

Bundle b = new Bundle();
b.putString("Key", "YourValue");
b.putInt("YourKey", 1);

FragmentB fragB = new FragmentB();
fragB.setArguments(b); 
getFragmentManager().beginTransaction().replace(R.id.your_container, fragB);

片段 B:

Bundle b = this.getArguments();
if(b != null){
   int i = b.getInt("YourKey");
   String s =b.getString("Key");
}

我发现这是从一个片段向另一个片段发送数据的最简单方法。希望能对某些人有所帮助。


3
您有几个选择:
选项1:如果您需要在片段之间共享信息,可以使用SharedPreferences存储信息。这是一个示例:
SharedPreferences settings = context.getSharedPreferences("Preferences", Context.MODE_PRIVATE);
    SharedPreferences.Editor editor = settings.edit();
    editor.putString("string1", var);
    editor.putBoolean("bool1", var);
    ...
    editor.commit();

选项2:如果您已经实例化了一个片段,您可以创建一个设置方法来在片段中存储某种信息。例如,如果您想要传递一个字符串数组,您可以在片段中创建一个数组变量(带有setter方法)。稍后,当您已经实例化这个片段时,您可以使用setter方法将这个数组传递到片段中。


1
你可以创建一个Application类(即扩展Application),然后获取所需变量,创建getter和setter方法。将值设置为变量并在需要时获取值。如果希望,我可以为您提供一些演示代码。

我喜欢得到一些请。 - Soufiane
获取一些什么,伙计? - Osman Goni Nahid

0
我们可以用两种方式在片段之间共享数据。
  1. 使用 Bundle

  2. 使用持久性存储

使用 Bundle:

Bundle bundle=new Bundle();
bundle.putString("firstName",Fist);
bundle.putString("LastName",lastN);

第二个持久化存储:- 您可以查看如何将数据存储在持久化存储中。 希望对您有所帮助


0

使用在官方ViewModel 文档 中提出的SharedViewModel。

首先实现fragment-ktx以更轻松地实例化您的viewmodel。

dependencies {
implementation "androidx.fragment:fragment-ktx:1.2.2"
}

然后,您只需要将要与其他片段共享的数据放入视图模型中即可。

class SharedViewModel : ViewModel() {
    val selected = MutableLiveData<Item>()

    fun select(item: Item) {
        selected.value = item
    }
}

最后,只需在每个片段中实例化您的viewModel,并从要设置数据的片段设置selected的值即可完成。 片段A
class MasterFragment : Fragment() {

    private val model: SharedViewModel by activityViewModels()

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        itemSelector.setOnClickListener { item ->
        model.select(item)
      }

    }
}

然后,在你的Fragment目标处,只需监听这个值

Fragment B

class DetailFragment : Fragment() {

        private val model: SharedViewModel by activityViewModels()

        override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
            super.onViewCreated(view, savedInstanceState)
            model.selected.observe(viewLifecycleOwner, Observer<Item> { item ->
                // Update the UI
            })
        }
    }

这个答案可以帮助你,https://dev59.com/nuo6XIcBkEYKwwoYNBln#60696777


-1

1. 使用 BroadCastReceiver(有点复杂)

2. 使用 SharePreference

3. 将数据保存到 MyApplication 扩展的 Application 中


我知道ShaePreferences,它是一种简单的方法,但我不认为sharedPref是为此而设计的。 - Soufiane

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接