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