Android: Passing data from child fragment to parent fragment

android, android-fragments

Solution

Android architecture components solution:

In case you are using Android architecture components, it possible to share data between all `Fragments` of an `Activity` with a `ViewModel`. Ensure `ViewModelProviders` makes use of `Activity` context to create `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.
        });
    }
}

Non Android architecture components solution:

You can use setTargetFragment and onActivityResult to achieve this.

Set FragmentParent instance as target fragment on FragmentChild instance i.e.

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();

In FragmentChild, wherever you are invoking the popBackStack, call onActivityResult on the set target Fragment. Use Bundle to pass on additional data.

Intent intent = new Intent();
intent.putExtra(FRAGMENT_KEY, "Ok");
getTargetFragment().onActivityResult(getTargetRequestCode(), Activity.RESULT_OK, intent);
getFragmentManager().popBackStack();

Back in FragmentParent, override the default onActivityResult method.

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);
           }
        }
    }
}  

Problem

I need to pass some data from the child fragment to the parent fragment that I will be able to read when I go back to the parent fragment. In detail: I have a FragmentActivity that calls FragmentParent. From FragmentParent I call FragmentChild like this: ``` FragmentChild fragmentChild = new FragmentChild(); FragmentTransaction transaction = getFragmentManager().beginTransaction(); transaction.replace(R.id.frl_view_container, fragmentChild); transaction.addToBackStack(null); ctransaction.commit(); ``` In FragmentChild I set a string value which I need to pass back to FragmentParent and then I return back to FragmentParent. ``` String result = "OK"; getFragmentManager().popBackStack(); ``` What is the best/proper way to read the result string in FragmentParent?

Original source