在 fragment/child 片段中分配主机侦听器的最佳位置在哪里?
Where is the best place to assign a host listener within a fragment/child fragment?
我有一个可重复使用的 NumberPickerDialogFragment,它可以由 activity 或片段管理。我读过的每个教程都会在 onAttach(Context) 覆盖中分配监听器。像这样:
@Override
public void onAttach(Context context) {
super.onAttach(context);
try {
listener = (Listener) context;
} catch (ClassCastException e) {
throw new ClassCastException(context.toString()
+ " must implement Listener");
}
}
显然,如果且仅当片段由 activity 托管时,这才有效。但是,如果片段也可以托管在另一个片段中怎么办?我读过 onCreateView 或 onViewCreated 或 onActivityCreated 可以工作对于这种情况。像这样:
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
try {
listener = (Listener) getParentFragment();
} catch (ClassCastException e) {
throw new ClassCastException(getParentFragment().toString()
+ " must implement Listener");
}
return super.onCreateView(inflater, container, savedInstanceState);
}
所以上面的代码都涵盖了其中一种情况,或者不是两种情况。现在,由于我的 Fragment 扩展自 DialogFragment,我有以下代码:
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
Fragment fragment = getParentFragment();
if (fragment != null) {
try {
listener= (Listener) fragment;
} catch (ClassCastException e) {
throw new ClassCastException(fragment.toString()
+ " must implement Listener");
}
} else {
Activity activity = getActivity();
try {
listener= (Listener) activity;
} catch (ClassCastException e) {
throw new ClassCastException(activity.toString()
+ " must implement Listener");
}
}
我只是担心这可能不是最好的方法,考虑到我看到的所有教程都在 onAttach() 覆盖中这样做。
那么我的问题是:
- 如果 onAttach 是分配主机侦听器的最佳位置,其中侦听器是 Activity,并且
- onCreateView 是分配主机侦听器的最佳位置,其中侦听器是父级 Fragment,
- 那么哪里是分配主机监听器的最佳位置,其中监听器既可以是 Activity 也可以是父级 Fragment?
经过几个月的试验和对 Android 的更多了解后,我找到了解决这个特殊难题的方法。
对我来说最好的地方是始终在 OnAttach() 方法中管理它。
调用 OnAttach() 时,我会在此处调用 getParent() 以确认此片段是直接将自身附加到 Activity 还是片段。参见示例代码:
@Override
public void onAttach(Context context) {
super.onAttach(context);
if (getParentFragment() == null) {
try {
mController = (Controller) context;
} catch (ClassCastException e) {
throw new ClassCastException(context.toString()
+ " must implement " + Controller.class.getName());
}
} else {
try {
mController = (Controller) getParentFragment();
} catch (ClassCastException e) {
throw new ClassCastException(getParentFragment().getClass().toString()
+ " must implement " + Controller.class.getName());
}
}
}
我有一个可重复使用的 NumberPickerDialogFragment,它可以由 activity 或片段管理。我读过的每个教程都会在 onAttach(Context) 覆盖中分配监听器。像这样:
@Override
public void onAttach(Context context) {
super.onAttach(context);
try {
listener = (Listener) context;
} catch (ClassCastException e) {
throw new ClassCastException(context.toString()
+ " must implement Listener");
}
}
显然,如果且仅当片段由 activity 托管时,这才有效。但是,如果片段也可以托管在另一个片段中怎么办?我读过 onCreateView 或 onViewCreated 或 onActivityCreated 可以工作对于这种情况。像这样:
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
try {
listener = (Listener) getParentFragment();
} catch (ClassCastException e) {
throw new ClassCastException(getParentFragment().toString()
+ " must implement Listener");
}
return super.onCreateView(inflater, container, savedInstanceState);
}
所以上面的代码都涵盖了其中一种情况,或者不是两种情况。现在,由于我的 Fragment 扩展自 DialogFragment,我有以下代码:
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
Fragment fragment = getParentFragment();
if (fragment != null) {
try {
listener= (Listener) fragment;
} catch (ClassCastException e) {
throw new ClassCastException(fragment.toString()
+ " must implement Listener");
}
} else {
Activity activity = getActivity();
try {
listener= (Listener) activity;
} catch (ClassCastException e) {
throw new ClassCastException(activity.toString()
+ " must implement Listener");
}
}
我只是担心这可能不是最好的方法,考虑到我看到的所有教程都在 onAttach() 覆盖中这样做。
那么我的问题是:
- 如果 onAttach 是分配主机侦听器的最佳位置,其中侦听器是 Activity,并且
- onCreateView 是分配主机侦听器的最佳位置,其中侦听器是父级 Fragment,
- 那么哪里是分配主机监听器的最佳位置,其中监听器既可以是 Activity 也可以是父级 Fragment?
经过几个月的试验和对 Android 的更多了解后,我找到了解决这个特殊难题的方法。
对我来说最好的地方是始终在 OnAttach() 方法中管理它。
调用 OnAttach() 时,我会在此处调用 getParent() 以确认此片段是直接将自身附加到 Activity 还是片段。参见示例代码:
@Override
public void onAttach(Context context) {
super.onAttach(context);
if (getParentFragment() == null) {
try {
mController = (Controller) context;
} catch (ClassCastException e) {
throw new ClassCastException(context.toString()
+ " must implement " + Controller.class.getName());
}
} else {
try {
mController = (Controller) getParentFragment();
} catch (ClassCastException e) {
throw new ClassCastException(getParentFragment().getClass().toString()
+ " must implement " + Controller.class.getName());
}
}
}