从片段调用时可以使AlertDialog起作用吗?

时间:2019-03-27 00:28:18

标签: android android-alertdialog android-dialogfragment

我有一个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的构造函数。

1 个答案:

答案 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"); } 方法中删除代码。