我有一个AlertDialog
可以和Activites
一起正常工作,但是由于AlertDialog.Builder(getActivity)
的原因,它不能用于Fragments。在这种情况下,父活动包含一个子Fragment
,该子RecyclerView
使用AlertDialog
来显示记录。当用户滑动记录时,将显示AlertDialog
以确认删除。但是,这不起作用,因为DialogFragment confirmDialog = new ConfirmDialogFragment();
confirmDialog.show(getFragmentManager(), "ConfirmDialogFragment");
引用了父活动。我在下面包括了AlertDialog的代码和AlertFragment的LogCat输出。
我在子Fragment中实例化ConfirmDialogFragment,如下所示:
package com.example.jbiss.petminder.dialogs;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.os.Bundle;
import android.util.Log;
import androidx.fragment.app.DialogFragment;
import com.example.jbiss.petminder.R;
import java.util.Set;
public class ConfirmDialogFragment extends DialogFragment {
private static final String TAG = "ConfirmDialogFragment";
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
Log.d(TAG, "Entered onCreateDialog");
if(savedInstanceState ==null){
Log.d(TAG, "savedInstanceState is null");
}else{
Set<String> s = savedInstanceState.keySet();
Log.d(TAG, "savedInstanceState is: " + s);
}
Log.d(TAG, "getParentFragment is: " + getParentFragment());
Log.d(TAG, "getContext is: " + getContext());
Log.d(TAG, "getActivity is: " + getActivity());
Log.d(TAG, "this is: " + this);
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
builder.setMessage(R.string.delete_confirm)
.setPositiveButton(R.string.delete, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
Log.d(TAG, "Delete clicked");
Log.d(TAG, "getContext is: " + getContext());
Log.d(TAG, "this is: " + this);
mListener.onDialogPositiveClick(ConfirmDialogFragment.this);
}
})
.setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
// User cancelled the dialog
Log.d(TAG, "Cancel clicked");
mListener.onDialogNegativeClick(ConfirmDialogFragment.this);
}
});
return builder.create();
}
public interface ConfirmDialogListener {
public void onDialogPositiveClick(DialogFragment dialog);
public void onDialogNegativeClick(DialogFragment dialog);
}
// Use this instance of the interface to deliver action events
ConfirmDialogListener mListener;
// Override the Fragment.onAttach() method to instantiate the ConfirmDialogListener
@Override
public void onAttach(Context context) {
super.onAttach(context);
Log.d(TAG, "Entered onAttach");
// Verify that the host activity implements the callback interface
try {
// Instantiate the NoticeDialogListener so we can send events to the host
mListener = (ConfirmDialogListener) context;
Log.d(TAG, "activity is: " + context);
Log.d(TAG, "mListener is: " + mListener);
} catch (ClassCastException e) {
// The activity doesn't implement the interface, throw exception
throw new ClassCastException(context.toString()
+ " must implement NoticeDialogListener");
}
}
}
AlertDialog Fragment代码如下所示:
MedicalInformationFragment: swiped to the 4!
MedicalInformationFragment: position swiped is: 0
ConfirmDialogFragment: Entered onAttach
ConfirmDialogFragment: activity is: com.example.jbiss.petminder.activities.PetInformationActivity@8963dda
ConfirmDialogFragment: mListener is: com.example.jbiss.petminder.activities.PetInformationActivity@8963dda
ConfirmDialogFragment: Entered onCreateDialog
ConfirmDialogFragment: savedInstanceState is null
ConfirmDialogFragment: getParentFragment is: null
ConfirmDialogFragment: getContext is: com.example.jbiss.petminder.activities.PetInformationActivity@8963dda
ConfirmDialogFragment: getActivity is: com.example.jbiss.petminder.activities.PetInformationActivity@8963dda
ConfirmDialogFragment: this is: ConfirmDialogFragment{a4e01a0 #2 ConfirmDialogFragment}
代码中显示的LogCat输出如下所示。
ConfirmDialogFragment: Delete clicked
ConfirmDialogFragment: getContext is: com.example.jbiss.petminder.activities.PetInformationActivity@8963dda
ConfirmDialogFragment: this is: com.example.jbiss.petminder.dialogs.ConfirmDialogFragment$2@c3512d0
PetInformationActivity: Entered onDialogPositiveClick
PetInformationViewModel: Entered: deletePetName
单击ConfirmDialogFragment的Delete键时,LogCat显示以下内容:
AlertDialog.Builder
从LogCat输出中可以看到,ConfirmDialogFragment确实返回到调用Fragment的ConfirmDialogFragment.ConfirmDialogListener接口方法,然后转到父Activity的方法。
这是由于getActivity()
被AlertDialog
实例化的事实,该实例获得父Activity的引用,而不是调用Fragment的引用。从LogCat输出中可以看出,尝试使用getContext还会引用父Activity。关于使用DialogFragment
的所有问题都指出,应该使用getActivity,因为它们似乎是在使用DialogFragment confirmDialog = new ConfirmDialogFragment(CallingFragmentReferenceSimilarToAnActivity);
confirmDialog.show(getFragmentManager(), "ConfirmDialogFragment");
,而不是有关调用它的Fragment。
是否要从片段中使用AlertDialog?可以将如下所示的Fragment等同于Activity的引用传递给AlertDialog的构造函数吗?
public class MyServiceImpl {
private MyDaoImpl dao;
private UserDetail userDetail;
......
}
public class MyDaoImpl {
private UserDetail userDetail;
......
}
我相信,在这种情况下,我应该能够过载AlertDialog的构造函数。
答案 0 :(得分:1)
这是由于AlertDialog.Builder是用getActivity()实例化的,该实例获取父Activity的引用,而不是调用Fragment的引用。
问题不在于AlertDialog
,而在于侦听器的设置方式。由于Fragment
的{{1}}方法返回了父getContext()
的上下文。
Activity
此行将您的侦听器设置为呼叫方mListener = (ConfirmDialogListener) context;
的父方Activity
。不必将Fragment
设置为父活动,而必须将其设置为调用片段。
首先,您必须在实例化时为mListener
设置目标片段。
DialogFragment
现在,在对话框片段的DialogFragment confirmDialog = new ConfirmDialogFragment();
confirmDialog.setTargetFragment(this, "CONFIRM_DIALOG_TAG");
if (getFragmentManager() != null) {
confirmDialog.show(getFragmentManager(), "ConfirmDialogFragment");
}
中,您可以将回调设置为您的片段。
onCreate
然后从try {
mListener = (ConfirmDialogListener) getTargetFragment();
} catch (ClassCastException e) {
throw new ClassCastException(context.toString()
+ " must implement ConfirmDialogListener");
}
方法中删除代码。