I want to open a dialog fragment
from A fragment
, and pass data to A fragment when the dialog fragment ends.
To do this, I defined an interface in the dialog fragment and implemented it in the A fragment.
The result was that the listener was null.
This is because onAttach()
used context
and context meant activity
.
The activity did not implement the interface.
Of course, it might have been nice to implement the interface in the activity, but I didn’t want it because the method role didn’t match the activity.
Is there no way?
WriteRoutineFragment.java (A Fragment)
public class WriteRoutineFragment extends Fragment implements WorkoutListDialogFragment.OnAddRoutineListener { RecyclerView routine_rv; List<RoutineModel> items; List<String> titleData; RoutineListAdapter listAdapter; public static WriteRoutineFragment newInstance(Bundle data) { WriteRoutineFragment f = new WriteRoutineFragment(); f.setArguments(data); return f; } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { ViewGroup rootView = (ViewGroup) inflater.inflate(R.layout.activity_write_routine, container, false); titleData = getArguments().getStringArrayList("title"); listAdapter = new RoutineListAdapter(diffUtil2); items = new ArrayList<>(); // routineAdapter = new RoutineAdapter(); routine_rv.setAdapter(listAdapter); // ADD Routine listAdapter.setOnAddRoutineClickListener(new RoutineListAdapter.OnAddRoutineClickListener() { @Override public void onAddRoutineClick() { WorkoutListDialogFragment routineDialog = new WorkoutListDialogFragment(); routineDialog.show(getActivity().getSupportFragmentManager(), "RoutineListDialog"); } }); return rootView; } @Override public void onAddRoutine(String routine) { RoutineModel routineModel = new RoutineModel(routine); RoutineDetailModel routineDetailModel = new RoutineDetailModel(); routineModel.addDetail(routineDetailModel); items.add(routineModel); List<Object> list = getUpdatedList(); listAdapter.submitList(list); } }
DialogFragment.java
public class WorkoutListDialogFragment extends DialogFragment { static final String TAG = "RoutineListDialog"; WorkoutListAdapter workoutListAdapter; OnAddRoutineListener listener; public interface OnAddRoutineListener { public void onAddRoutine(String routine); } @Override public void onAttach(@NonNull Context context) { super.onAttach(context); if(context != null && context instanceof OnAddRoutineListener) { listener = (OnAddRoutineListener) context; // null } return; } @Nullable @Override public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { View view = inflater.inflate(R.layout.fragment_workout_list_dialog, container, false); routineListRecycler = view.findViewById(R.id.routine_list_recycler); rountineChipGroup = view.findViewById(R.id.routine_chipgroup); workoutListAdapter.setOnWorkoutListClickListener(new WorkoutListAdapter.OnWorkoutListItemClickListener() { @Override public void OnItemClick(String routine) { if(listener != null) { listener.onAddRoutine(routine); dismiss(); } } }); return view; } }
Advertisement
Answer
To handle this kind of problem Live Data comes to play. By using Live Data we can pass data between fragments with out any issue. Just create a View Model like below:
public class RoutineViewModel extends ViewModel { private MutableLiveData<String> mRoutine; public RoutineViewModel() { mRoutine = new MutableLiveData(); } public void setRoutine(String data){ mRoutine.setValue(data); } public LiveData<String> getRoutine(){ return mRoutine;} }
And use this View Model
in both the fragments in order to get the latest updated value of Live Data
.
Using View Model
and Live Data
in WriteRoutineFragment looks like below:
private RoutineViewModel routineViewModel; public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { routineViewModel = new ViewModelProvider(requireActivity()).get(RoutineViewModel.class); View root = inflater.inflate(R.layout.fragment_home, container, false); routineViewModel.getRoutine().observe(getViewLifecycleOwner(), new Observer<String>() { @Override public void onChanged(String s) { Log.d("TAG==>>","Routine changed = "+s); } }); listAdapter.setOnAddRoutineClickListener(new RoutineListAdapter.OnAddRoutineClickListener() { @Override public void onAddRoutineClick() { WorkoutListDialogFragment routineDialog = new WorkoutListDialogFragment(); routineDialog.show(getChildFragmentManager(), "RoutineListDialog"); } }); return root; }
Using View Model
and Live Data
in WorkoutListDialogFragment looks like below:
public class WorkoutListDialogFragment extends DialogFragment { private RoutineViewModel routineViewModel; WorkoutListAdapter workoutListAdapter; public WorkoutListDialogFragment() { // Required empty public constructor } @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); routineViewModel = new ViewModelProvider(requireActivity()).get(RoutineViewModel.class); } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { // Inflate the layout for this fragment return inflater.inflate(R.layout.fragment_workout_list_dialog, container, false); } @Override public void onViewCreated(@NonNull View view, Bundle savedInstanceState){ workoutListAdapter.setOnWorkoutListClickListener(new WorkoutListAdapter.OnWorkoutListItemClickListener() { @Override public void OnItemClick(String routine) { routineViewModel.setRoutine(routine); dismiss(); } }); } }