Android:从子片段传递数据到父片段

12

我需要将一些数据从子片段传递到父片段,以便在返回到父片段时能够读取。具体来说:

我有一个调用 FragmentParent 的 FragmentActivity。从 FragmentParent 我这样调用 FragmentChild:

FragmentChild fragmentChild = new FragmentChild();
FragmentTransaction transaction = getFragmentManager().beginTransaction();
transaction.replace(R.id.frl_view_container, fragmentChild);
transaction.addToBackStack(null);
ctransaction.commit();

在FragmentChild中,我设置了一个字符串值,需要将其传递回FragmentParent,然后返回到FragmentParent。

String result = "OK";
getFragmentManager().popBackStack();

在FragmentParent中,读取结果字符串的最佳/适当方式是什么?

1个回答

46

Android架构组件解决方案:

如果您正在使用Android架构组件,可以通过一个ViewModelActivity的所有Fragments之间共享数据。确保ViewModelProviders使用Activity上下文来创建ViewModels

public class SharedViewModel extends ViewModel {
    private final MutableLiveData<Item> selected = new MutableLiveData<Item>();

    public void select(Item item) {
        selected.setValue(item);
    }

    public LiveData<Item> getSelected() {
        return selected;
    }
}

public class MasterFragment extends Fragment {
    private SharedViewModel model;
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        model = ViewModelProviders.of(getActivity()).get(SharedViewModel.class);
        itemSelector.setOnClickListener(item -> {
            model.select(item);
        });
    }
}

public class DetailFragment extends Fragment {
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        SharedViewModel model = ViewModelProviders.of(getActivity()).get(SharedViewModel.class);
        model.getSelected().observe(this, { item ->
           // Update the UI.
        });
    }
}

非Android架构组件解决方案:

您可以使用setTargetFragmentonActivityResult来实现此功能。

将FragmentParent实例设置为FragmentChild实例的目标碎片。

FragmentChild fragmentChild = new FragmentChild();
fragmentChild.setTargetFragment(this, FRAGMENT_CODE);
FragmentTransaction transaction = getFragmentManager().beginTransaction();
transaction.replace(R.id.frl_view_container, fragmentChild);
transaction.addToBackStack(null);
transaction.commit();
在FragmentChild中,无论您何时调用popBackStack,请在目标Fragment上调用onActivityResult。使用Bundle传递额外的数据。
Intent intent = new Intent();
intent.putExtra(FRAGMENT_KEY, "Ok");
getTargetFragment().onActivityResult(getTargetRequestCode(), Activity.RESULT_OK, intent);
getFragmentManager().popBackStack();

回到 FragmentParent,在其中重写默认的 onActivityResult 方法。

public void onActivityResult(int requestCode, int resultCode, Intent data) {
    if(requestCode == FRAGMENT_CODE && resultCode == Activity.RESULT_OK) {
        if(data != null) {
           String value = data.getStringExtra(FRAGMENT_KEY);
           if(value != null) {
              Log.v(TAG, "Data passed from Child fragment = " + value);
           }
        }
    }
}  

1
这个可以运行,但我无法在onActivityResult中更新UI。你能帮忙吗? - Farooq Arshed
@Farooq Arshed:对于UI更新,您需要刷新您的视图。例如,我正在使用适配器,那么我只需要在onActivityResult中通知我的适配器即可。就这样。 - Shailesh
@Manish Mulimani 一旦我这样做了,这会调用我的选项卡片段的onStart吗?因为我正在从服务器获取数据,并且我的某些变量已经在onStart中初始化。 - Erum
问题在于onCreateViewonActivityResult之后立即调用,重新创建所有视图为初始状态。 - Konstantin Konopko
为了更新UI,我使用了onResume()+static_fields,而不是ChildFragment+listeners,但是关于片段实例没有任何保证,实例可能会再次创建,只能从参数中创建,有时在gc()之后。因此,只有SharedPreferences和文件系统可以100%可靠。 - user3002379
显示剩余2条评论

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