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