在片段之间调用方法时,必须经过activity吗?
When calling a method between fragments, must it go through an activity?
我想从A fragment
打开一个dialog fragment
,并在对话片段结束时将数据传递给A片段。
为此,我在对话框片段中定义了一个接口并在 A 片段中实现了它。
结果是侦听器为空。
这是因为 onAttach()
使用了 context
并且上下文意味着 activity
。
activity没有实现接口。
当然,在activity中实现接口可能很好,但我不想要它,因为方法角色与activity不匹配。
没有办法吗?
WriteRoutineFragment.java(片段)
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;
}
}
为了处理这类问题,实时数据 上场了。通过使用实时数据,我们可以毫无问题地在片段之间传递数据。只需创建一个 View 模型,如下所示:
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;}
}
并在两个片段中使用此 View Model
以获得 Live Data
的最新更新值。
在 WriteRoutineFragment 中使用 View Model
和 Live Data
如下所示:
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;
}
在 WorkoutListDialogFragment 中使用 View Model
和 Live Data
如下所示:
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();
}
});
}
}
在显示对话框时使用 getChildFragmentManager()
而不是 getActivity().getSupportFragmentManager()
,现在上下文将绑定到片段并且侦听器不会为 null
listAdapter.setOnAddRoutineClickListener(new RoutineListAdapter.OnAddRoutineClickListener() {
@Override
public void onAddRoutineClick() {
WorkoutListDialogFragment routineDialog = new WorkoutListDialogFragment();
routineDialog.show(getChildFragmentManager(), "RoutineListDialog");
}
});
我想从A fragment
打开一个dialog fragment
,并在对话片段结束时将数据传递给A片段。
为此,我在对话框片段中定义了一个接口并在 A 片段中实现了它。
结果是侦听器为空。
这是因为 onAttach()
使用了 context
并且上下文意味着 activity
。
activity没有实现接口。
当然,在activity中实现接口可能很好,但我不想要它,因为方法角色与activity不匹配。
没有办法吗?
WriteRoutineFragment.java(片段)
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;
}
}
为了处理这类问题,实时数据 上场了。通过使用实时数据,我们可以毫无问题地在片段之间传递数据。只需创建一个 View 模型,如下所示:
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;}
}
并在两个片段中使用此 View Model
以获得 Live Data
的最新更新值。
在 WriteRoutineFragment 中使用 View Model
和 Live Data
如下所示:
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;
}
在 WorkoutListDialogFragment 中使用 View Model
和 Live Data
如下所示:
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();
}
});
}
}
在显示对话框时使用 getChildFragmentManager()
而不是 getActivity().getSupportFragmentManager()
,现在上下文将绑定到片段并且侦听器不会为 null
listAdapter.setOnAddRoutineClickListener(new RoutineListAdapter.OnAddRoutineClickListener() {
@Override
public void onAddRoutineClick() {
WorkoutListDialogFragment routineDialog = new WorkoutListDialogFragment();
routineDialog.show(getChildFragmentManager(), "RoutineListDialog");
}
});