如果从Fragment调用,则DialogFragment抛出ClassCastException [英] DialogFragment throws ClassCastException if called from Fragment
问题描述
如果从Fragment调用,我的DialogFragment会抛出 ClassCastException ,而从Activity调用时,它将正常工作.我已经看过其他一些具有类似问题的问题,基本上这些问题都与导入有关,但是我无法在实现中解决它.这是我对DialogFragment的实现.
My DialogFragment throws ClassCastException if called from Fragment, while it is working normally if called from an Activity. I have already looked at few other questions with similar problem and basically those are related to imports, but I haven't been able to solve it in my implementation. Here is my implementation for 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的片段:
Here is my Fragment that is using the above 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):位于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):at android.app.FragmentManagerImpl $ 1.run(FragmentManager.java:426) 02-01 13:11:32.750:E/AndroidRuntime(15061):at 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):at 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(本机方法) 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):在com.android.internal.os.ZygoteInit $ MethodAndArgsCaller.run(ZygoteInit.java:1006) 02-01 13:11:32.750:E/AndroidRuntime(15061):在com.android.internal.os.ZygoteInit.main(ZygoteInit.java:773) 02-01 13:11:32.750:E/AndroidRuntime(15061):在dalvik.system.NativeStart.main(本机方法)
02-01 13:11:32.750: E/AndroidRuntime(15061): FATAL EXCEPTION: main 02-01 13:11:32.750: E/AndroidRuntime(15061): java.lang.ClassCastException: com.milanix.tuki.UiMainActivity@41d75350 must implement 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): at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:787) 02-01 13:11:32.750: E/AndroidRuntime(15061): at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:1035) 02-01 13:11:32.750: E/AndroidRuntime(15061): at android.app.BackStackRecord.run(BackStackRecord.java:635) 02-01 13:11:32.750: E/AndroidRuntime(15061): at android.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1397) 02-01 13:11:32.750: E/AndroidRuntime(15061): at android.app.FragmentManagerImpl$1.run(FragmentManager.java:426) 02-01 13:11:32.750: E/AndroidRuntime(15061): at android.os.Handler.handleCallback(Handler.java:615) 02-01 13:11:32.750: E/AndroidRuntime(15061): at android.os.Handler.dispatchMessage(Handler.java:92) 02-01 13:11:32.750: E/AndroidRuntime(15061): at android.os.Looper.loop(Looper.java:137) 02-01 13:11:32.750: E/AndroidRuntime(15061): at 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)
我想知道是否有人可以给这个问题一个提示.
I am wondering if anyone can give a hint about this issue.
推荐答案
来自文档:
onAttach(Activity) called once the fragment is associated with its activity.
在您的代码中
mListener = (SetupHotspotDialogListener) activity;
行抛出ClassCastException
,因为您的活动未实现SetupHotspotDialogListener
接口. (Fragment
与包含它的活动直接相关,因为DialogFragment
扩展了Fragment
,所以它与DialogFragment
也有直接关系.)
line throws ClassCastException
because your activity don't implement SetupHotspotDialogListener
interface. (Fragment
is directly tied to the activity that contains it, as well as DialogFragment
because DialogFragment
extends Fragment
).
再次从文档
在某些情况下,您可能需要一个片段来与活动共享事件.做到这一点的一个好方法是在片段内定义一个回调接口,并要求主机活动实现它.当活动通过接口收到回调时,它可以根据需要与布局中的其他片段共享信息.
In some cases, you might need a fragment to share events with the activity. A good way to do that is to define a callback interface inside the fragment and require that the host activity implement it. When the activity receives a callback through the interface, it can share the information with other fragments in the layout as necessary.
因此,如果您想从Fragment
创建FragmentDialog
,我建议通过活动的回调对其进行组织:
So if you want to create FragmentDialog
from Fragment
I suggest to organize it via callbacks to activity:
- 使用
createDialogRequest()
之类的方法在您的SmartMode
Fragment
类中创建回调接口(就像您对dialogFragment所做的一样). - 让您的活动实现该界面
- 然后,当您需要创建对话框时,将回调从
Fragment
发送到Activity
- 将显示对话框逻辑"放入
Activity
- create callback interface into your
SmartMode
Fragment
class (like you do into dialogFragment) with one method likecreateDialogRequest()
. - let your activity implement that interface
- then, when you need to create dialog, send callback from
Fragment
toActivity
- place "show dialog logics" into
Activity
看起来就像片段询问活动创建对话框,活动显示对话框.
It's look like fragment ask activity to create dialog, activity shows dialog.
我想我已经找到了您需要的更好的实现.我编写了一个简单的示例,该示例从片段创建fragment dialog
,并将fragment dialog
回调事件接收到片段中.
EDITED:
I think i had found better implementation of what you need. I've write a simple example of creating fragment dialog
from fragment with receiving fragment dialog
callback events into fragment.
活动:
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:
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个库片段
I used support 4 library fragments
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>
该想法是将引用发送到将捕获回调事件的接口.
The idea is to send reference to interface which will catch callback events.
这篇关于如果从Fragment调用,则DialogFragment抛出ClassCastException的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!