在DialogFragment中,onAttach()方法从未被调用

5

我尝试从一个DialogFragment中实现回调。有一个很好的例子,但是他们没有从一个Fragment中打开这个DialogFragmenthttp://developer.android.com/guide/topics/ui/dialogs.html#PassingEvents

所以这是我的代码:

public class EditDateDialogFragment extends DialogFragment {
    // Use this instance of the interface to deliver action events
    EditDateDialogListener mListener;

    /* The activity that creates an instance of this dialog fragment must
     * implement this interface in order to receive event callbacks.
     * Each method passes the DialogFragment in case the host needs to query it. */
    public interface EditDateDialogListener {
        public void onDialogPositiveClick(DialogFragment dialog);
        public void onDialogNegativeClick(DialogFragment dialog);
    }


    public static EditDateDialogFragment newInstance( int currentCategoryId ) {
        EditDateDialogFragment p = new EditDateDialogFragment();
        Bundle args = new Bundle();
        args.putInt("currentRecordId", currentCategoryId);
        p.setArguments(args);
        return p;
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        mCurrentRecordId = getArguments().getInt("currentRecordId");
        super.onCreate(savedInstanceState);
    }

    public void onAttach(SherlockActivity activity) {

        super.onAttach(activity);

        try {
            // Instantiate the EditDateDialogListener so we can send events to the host
            mListener = (EditDateDialogListener) activity;
        } catch (ClassCastException e) {
            // The activity doesn't implement the interface, throw exception
            throw new ClassCastException(activity.toString() + " must implement EditDateDialogListener");
        }

    }

        @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {
        LayoutInflater inflater = LayoutInflater.from(getActivity());
        final View v = inflater.inflate(R.layout.fragment_dialog_edit_date, null);

        return new AlertDialog.Builder(getActivity()).setTitle("Set Date...").setView(v).setCancelable(true).setPositiveButton("Confirm", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                Log.d("", "Dialog confirmed");

                mListener.onDialogPositiveClick(EditDateDialogFragment.this);

            }
        }).setNegativeButton("Abort", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                Log.d("", "Dialog abort");
                dialog.cancel();
            }
        }).create();
    }
}

在RecordDetailFragment.java中,我实现了接口并按以下方式创建EditDateDialogFragment的新实例(仅列出重要部分):
public class RecordDetailFragment extends SherlockFragment implements EditDateDialogFragment.EditDateDialogListener {
...
 DialogFragment editDateFragment = EditDateDialogFragment.newInstance( recordId );
             editDateFragment.show(getActivity().getSupportFragmentManager(), "EditDateDialogFrame");
@Override
    public void onDialogPositiveClick(DialogFragment dialog) {
        LOGD(TAG, "Overriden Dialog confirmed");
        //((EditDateDialogFragment) dialog).mDatePicker;

    }

    @Override
    public void onDialogNegativeClick(DialogFragment dialog) {
        // TODO Auto-generated method stub

    }
...
}

现在,EditDateDialogFragment中的onAttach(SherlockActivity activity)方法从未被调用,因为我是从Fragment而不是Activity中创建DialogFragment。 如何解决这个问题?
更新: 在RecordDetailFragment中,我将这个插入到onCreate()中。
if (savedInstanceState != null) {
    EditDateDialogFragment dpf = (EditDateDialogFragment) getActivity().getSupportFragmentManager().findFragmentByTag("EditDateDialogFragment");
    if (dpf != null) {
        dpf.setListener((EditDateDialogListener) this);
    }
}

我将DialogFragment的实例化方式更改为

 EditDateDialogFragment editDateFragment = EditDateDialogFragment.newInstance( recordId );
             editDateFragment.setListener((EditDateDialogListener) this);
             editDateFragment.show(getActivity().getSupportFragmentManager(), "EditDateDialogFragment");

请注意使用EditDateDialogFragment而不是DialogFragment。 我不确定如何在对话框中更新参考文献。
4个回答

10

我也遇到了同样的问题,解决方法非常简单。不要重写。

public void onAttach(Context context) {}

覆盖这个:

public void onAttach(Activity activity) {}

现在DialogFragment一切都很好。


9

如何解决这个问题?

我猜想您希望RecordDetailFragment实例作为EditDateDialogListener来处理DialogFragment。如果是这样,那么您需要明确地设置它(并更新它)作为监听器:

DialogFragment editDateFragment = EditDateDialogFragment.newInstance( recordId );
editDataFragment.setListener(RecordDetailFragment.this);
editDateFragment.show(getActivity().getSupportFragmentManager(), "EditDateDialogFrame");

setListener()EditDialogFragment 中的一个方法,如下:

public void setListener(EditDateDialogListener listener) {
     mListener = listener;
}

当用户旋转手机时,例如,Activity及其片段将被重新创建,您需要重新设置侦听器以指向新创建的RecordDetailFragment实例(您可能希望使用WeakReference来处理mListener)。您可以在此答案中找到类似的内容(您将查找onCreate中的两个片段)。 编辑:在Activity的onCreate方法中:
if (savedInstanceState != null) {
    RecordDetailFragment df = (RecordDetailFragment) getSupportFragmentManager().findFragmentByTag("rdf"); // "rdf" is the tag used when you add the RecordDetailFragment to the activity
    EditDateDialogFragment s = (EditDateDialogFragment) getSupportFragmentManager().findFragmentByTag("tag"); // "tag" is the string set as the tag for the dialog when you show it
    if (s != null) {
                   // the dialog exists so update its listener
        s.setListener(df);
    }
}

我无法让监听器更新起作用。您在评论中提到的需要更新监听器引用的描述对我来说有点不太明确。 - No3x
@No3x,你能分享一些关于如何更新监听器的信息/代码吗? - user
我有点困惑...是在哪个活动中?我想在Fragment和DialogFragment之间进行通信。 - No3x
@No3x,那么这两个代码片段在哪里使用?它们不是放置在“FragmentActivity”/“Activity”中的吗? - user

3
在onCreateDialog中,将mListener强制转换为getActivity():
try {
    mListener = (EditDateDialogListener) getActivity();
} catch (Exception e) {
    throw new ClassCastException(getActivity().toString()
            + " must implement EditDateDialogListener");
}

0
一个更“现代”的方法是使用新的Fragment Result API
在Fragment A(父)的onCreate中添加结果监听器:
override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)

    childFragmentManager.setFragmentResultListener("requestKey", this) { key, bundle ->
        val result = bundle.getString("bundleKey")
    }

}

无论在哪里,都可以在子片段B上设置结果(例如,在按钮点击侦听器上):

button.setOnClickListener {
    val result = "resultSample"

    setFragmentResult("requestKey", bundleOf("bundleKey" to result))
}

更多信息请参阅文档:https://developer.android.com/guide/fragments/communicate#kotlin


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接