如果从Fragment调用,我的DialogFragment将抛出 ClassCastException ,而如果从Activity调用它则正常工作。我已经看过几个有类似问题的其他问题,基本上那些与导入有关,但我在实现中无法解决它。这是我对DialogFragment的实现。
import android.app.AlertDialog; import android.app.Dialog; import android.app.DialogFragment; public class HotspotScanDialog extends DialogFragment { SetupHotspotDialogListener mListener; @Override public Dialog onCreateDialog(Bundle savedInstanceState) { ... .setAdapter(hotspotAdapter, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { mListener.onHotspotSelectedListener(hotspotAdapter.getItem( which).toString()); } })... } public interface SetupHotspotDialogListener { public void onHotspotSelectedListener(String selection); } @Override public void onAttach(Activity activity) { super.onAttach(activity); try { mListener = (SetupHotspotDialogListener) activity; } catch (ClassCastException ignore) { // Just to make sure if anyone will be pointing at my throwing // ClassCastException myself I have tried without this code as well. throw new ClassCastException(activity.toString() + " must implement NoticeDialogListener"); } } }
这是我使用上述DialogFragment的片段:
import android.app.AlertDialog; import android.app.DialogFragment; import android.support.v4.app.Fragment; import com.xxx.yyy.ui.compontent.dialog.HotspotScanDialog; import com.xxx.yyy.ui.compontent.dialog.HotspotScanDialog.SetupHotspotDialogListener; public class SmartMode extends Fragment implements SetupHotspotDialogListener { private void showWifiSelectionDialog() { DialogFragment setupWifiSelectionDialog = new HotspotScanDialog(); /* * using getFragmentManager() only says "The method * show(FragmentManager, String) in the type DialogFragment is not * applicable for the arguments (FragmentManager, String)" */ setupWifiSelectionDialog.show(getActivity().getFragmentManager(), Keys.TAG.toString()); } @Override public void onHotspotSelectedListener(String selection) { // Log.d(TAG,selection); } }
这是错误日志:
02-01 13:11:32.750:E / AndroidRuntime(15061):致命异常:主要 02-01 13:11:32.750:E / AndroidRuntime(15061):java.lang.ClassCastException:com.milanix.tuki.UiMainActivity@41d75350必须实现NoticeDialogListener 02-01 13:11:32.750:E / AndroidRuntime(15061):at com.xxx.yyy.ui.compontent.dialog.HotspotScanDialog.onAttach(HotspotScanDialog.java:122) 02-01 13:11:32.750:E / AndroidRuntime(15061):在android.app.FragmentManagerImpl.moveToState(FragmentManager.java:787) 02-01 13:11:32.750:E / AndroidRuntime(15061):在android.app.FragmentManagerImpl.moveToState(FragmentManager.java:1035) 02-01 13:11:32.750:E / AndroidRuntime(15061):在android.app.BackStackRecord.run(BackStackRecord.java:635) 02-01 13:11:32.750:E / AndroidRuntime(15061):在android.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1397) 02-01 13:11:32.750:E / AndroidRuntime(15061):在android.app.FragmentManagerImpl $ 1.run(FragmentManager.java:426) 02-01 13:11:32.750:E / AndroidRuntime(15061):在android.os.Handler.handleCallback(Handler.java:615) 02-01 13:11:32.750:E / AndroidRuntime(15061):在android.os.Handler.dispatchMessage(Handler.java:92) 02-01 13:11:32.750:E / AndroidRuntime(15061):在android.os.Looper.loop(Looper.java:137) 02-01 13:11:32.750:E / AndroidRuntime(15061):在android.app.ActivityThread.main(ActivityThread.java:4898) 02-01 13:11:32.750:E / AndroidRuntime(15061):at java.lang.reflect.Method.invokeNative(Native Method) 02-01 13:11:32.750:E / AndroidRuntime(15061):at java.lang.reflect.Method.invoke(Method.java:511) 02-01 13:11:32.750:E / AndroidRuntime(15061):at com.android.internal.os.ZygoteInit $ MethodAndArgsCaller.run(ZygoteInit.java:1006) 02-01 13:11:32.750:E / AndroidRuntime(15061):at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:773) 02-01 13:11:32.750:E / AndroidRuntime(15061):at dalvik.system.NativeStart.main(Native Method)
我想知道是否有人可以暗示这个问题。
答案 0 :(得分:12)
来自docs:
onAttach(Activity) called once the fragment is associated with its activity.
在您的代码中
mListener = (SetupHotspotDialogListener) activity;
行抛出ClassCastException
因为您的活动未实现SetupHotspotDialogListener
界面。 (Fragment
与包含它的活动直接相关,以及DialogFragment
,因为DialogFragment
扩展了Fragment
)。
再次来自docs
在某些情况下,您可能需要一个片段来与活动共享事件。一种好方法是在片段内定义一个回调接口,并要求主机活动实现它。当活动通过接口收到回调时,它可以根据需要与布局中的其他片段共享信息。
因此,如果您想从FragmentDialog
创建Fragment
,我建议您通过回调来组织活动:
SmartMode
等方法在Fragment
createDialogRequest()
类中创建回调接口(就像使用dialogFragment一样)。Fragment
发送到Activity
Activity
看起来像片段询问活动来创建对话框,活动显示对话框。
EDITED:
我想我已经找到了更好的实现你需要的东西。我写了一个简单的例子,从片段创建fragment dialog
,接收fragment dialog
回调事件到片段。
的活动:
public class MyFragmentActivity extends FragmentActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_my_fragment);
// first start of activity
if (savedInstanceState == null) {
// put fragment to activity layout
MyFragment fragment = new MyFragment();
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.replace(R.id.fragmentContainer, fragment, "fragment");
ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
ft.commit();
}
}
}
片段:
public class MyFragment extends Fragment implements MyDialogInterface {
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
super.onCreateView(inflater, container, savedInstanceState);
View fragmentView = inflater.inflate(R.layout.fragment, null);
// button which shows dialog
Button showDialogButton = (Button) fragmentView.findViewById(R.id.showDialog);
showDialogButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// create fragment dialog.
FragmentDialog dialog = FragmentDialog.getInstance(MyFragment.this);
dialog.show(getActivity().getSupportFragmentManager(), "dialog");
}
});
return fragmentView;
}
@Override
public void onClickEvent() {
// receive click events from dialog fragment
Log.e(getClass().getSimpleName(), "onClickEvent");
}
}
FragmentDialog:
public class FragmentDialog extends DialogFragment {
public interface MyDialogInterface extends Serializable {
public void onClickEvent();
}
private MyDialogInterface callbackListener;
/**
* dialogInterface - instance of MyDialogInterface which will handle
* callback events
*/
public static FragmentDialog getInstance(MyDialogInterface dialogInterface) {
FragmentDialog fragmentDialog = new FragmentDialog();
// set fragment arguments
Bundle args = new Bundle();
args.putSerializable("dialogInterface", dialogInterface);
fragmentDialog.setArguments(args);
return fragmentDialog;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setStyle(STYLE_NO_TITLE, 0);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View pushDialogView = getActivity().getLayoutInflater().inflate(R.layout.fragment_dialog, null);
// get reference to MyDialogInterface instance from arguments
callbackListener = (MyDialogInterface) getArguments().getSerializable("dialogInterface");
Button cancelButton = (Button) pushDialogView.findViewById(R.id.button);
cancelButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// send click event
callbackListener.onClickEvent();
}
});
return pushDialogView;
}
}
我使用了支持4个库片段
android.support.v4.app.Fragment
android.support.v4.app.DialogFragment
android.support.v4.app.FragmentActivity
布局:
activity_my_fragment.xml
:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/fragmentContainer"
android:layout_width="match_parent"
android:layout_height="match_parent" />
fragment.xml
:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#a00"
android:orientation="vertical" >
<Button
android:id="@+id/showDialog"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="show doalog" />
</LinearLayout>
fragment_dialog.xml
:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#fe3"
android:orientation="vertical" >
<Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="click me" />
</LinearLayout>
这个想法是发送引用接口,它将捕获回调事件。
答案 1 :(得分:-1)
public class HotspotScanDialog extends DialogFragment {
...
SetupHotspotDialogListener mListener;
...
@Override
public void onAttachFragment(Fragment childFragment) {
super.onAttachFragment(childFragment);
mListener = (SetupHotspotDialogListener) childFragment;
}
...
}
以及在Fragment中调用DialogFragment的
HotspotScanDialog dialog = new HotspotScanDialog();
dialog.show(getChildFragmentManager(), "TAG");