【问题标题】:android - handle dialogFragment buttons clicksandroid - 处理 dialogFragment 按钮的点击
【发布时间】:2017-09-01 12:09:34
【问题描述】:

我的应用中有 Activity,其中有几个片段。其中一个片段有一个 DialogFragment,它通过按钮单击调用。 DialogFragment 有 3 个按钮 - 正面、负面和中性。

public class CompanyNotConnectedToSRDialog extends DialogFragment {

    public static final String TAG = CompanyNotConnectedToSRDialog.class.getSimpleName();

    private NotConnectedDialogListener mNotConnectedDialogListener;

    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {
        return new AlertDialog.Builder(getActivity(), R.style.DefaultAlertDialogTheme)
                .setTitle("Register")
                .setMessage("Do you really want to register?")
                .setNeutralButton("Skip", (dialog1, which) -> {
                    mNotConnectedDialogListener.onSkipBtnNotConnectedDialogPressed();
                })
                .setNegativeButton("Cancel", null)
                .setPositiveButton("Register", (dialog12, which) -> {
                    mNotConnectedDialogListener.onSendBtnNotConnectedDialogPressed();
                })
                .create();
    }


    public interface NotConnectedDialogListener {
        void onSkipBtnNotConnectedDialogPressed();
        void onSendBtnNotConnectedDialogPressed();
    }

    public void setListener(NotConnectedDialogListener listener) {
        this.mNotConnectedDialogListener = listener;
    }

如您所见,我创建了公共接口,其中包含用于跳过和注册按钮的两个方法(取消按钮侦听器为空,因此没关系)和此侦听器的 Setter。 然后我在调用这个dialogFragment的片段中实现了这个接口,我重写了方法并像这样调用了dialogFragment:

if (mNotConnectedDialog == null) {
            mNotConnectedDialog = new CompanyNotConnectedToSRDialog();
            mNotConnectedDialog.setListener(this);
            mNotConnectedDialog.show(getActivity().getFragmentManager(), CompanyNotConnectedToSRDialog.TAG);
        } else {
            mNotConnectedDialog.show(mActivity.getFragmentManager(), CompanyNotConnectedToSRDialog.TAG);
            mNotConnectedDialog.setListener(this);
        }

问题是如果我按下父片段中的按钮以显示 DialogFragment、旋转屏幕并按下 DialogFragment 中的任何按钮,我会收到 NullPointerException,因为我的侦听器为空。

java.lang.NullPointerException: Attempt to invoke interface method 'void com.myapp.ui.object.create.dialogs.CompanyNotConnectedToSRDialog$NotConnectedDialogListener.onSendBtnNotConnectedDialogPressed()' on a null object reference

at com.myapp.ui.object.create.dialogs.CompanyNotConnectedToSRDialog.lambda$onCreateDialog$1(CompanyNotConnectedToSRDialog.java:31)

如果这个解决方案有问题,如何处理这些点击并设置监听器?

PS:请不要告诉我android:configChanges

【问题讨论】:

    标签: android fragment android-dialogfragment


    【解决方案1】:

    因此当前的解决方案不起作用,因为当您旋转对话框片段时,它会被销毁并重新创建。所以 setListener 没有被调用。解决方案取决于您的侦听器是活动还是另一个片段。

    如果它是一个活动,您可以在 DialogFragment 中覆盖 onAttach 并在那里设置监听器。如果您的侦听器是一个片段,那么在您的 OnCreateDialog 方法中,您可以通过标签查找片段并以这种方式设置侦听器。例如。

    Fragment listenerFragment = getActivity().getSupportFragmentManager().findFragmentByTag(getString(R.string.your_listener_fragment_tag));
    
    if( listenerFragment instanceOf NotConnectedDialogListener ) {
        listener = (NotConnectedDialogListener) listenerFragment;
    } else {
        //Handle what to do if you don't have a listener here. Maybe dismiss the dialog. 
    }
    

    【讨论】:

    • 不,不起作用。我做了同样的事情,并在“else”语句中添加了 ClassCastException,我的应用程序因.. ClassCastException 而崩溃。因为 listenerFragment = null
    • 好吧,我使用了 getFragmentManager 而不是 getSupportFragmentManager 因为我没有它……
    • 是的,这取决于您是否使用支持库。如果你不是那么 getFragmentManager 很好。在我的示例中,我有一种类型,分配应该使用 listenerFragment 而不是片段。我已经更新了。你不应该真的得到一个强制转换异常,因为 if 应该阻止它。你能分享一下你做了什么以及发生异常的那一行吗?
    • 没关系,我使用了支持库,现在它可以工作了。谢谢。但我还有一个问题——这个解决方案是一个好的解决方案吗?还是“最后一口气”的解决方案? :)
    • 就片段而言,我认为这是一个很好的解决方案。使用片段管理器来查找它所在的片段并没有错。不幸的是,它不如使用活动和 onAttach 方法那么优雅。但我喜欢你在我的代码中有很多地方需要使用片段并且不能使用活动,这就是我采取的路线。
    【解决方案2】:

    是的,在方向更改后,您的侦听器为空。对活动进行回调是最简单的:

    public static class DialogFragmentA extends DialogFragment {
    
        // Container Activity must implement this interface
        public interface NotConnectedDialogListener {
            public void onX();
        }
    
        NotConnectedDialogListener mListener;
        ...
        @Override
        public void onAttach(Activity activity) {
            super.onAttach(activity);
            try {
                mListener = (NotConnectedDialogListener) activity;
            } catch (ClassCastException e) {
                throw new ClassCastException(activity.toString() + " must implement NotConnectedDialogListener");
            }
        }
        ...
    }
    

    现在您可以在对话框中的任何位置调用 mListener.onX 等,也可以在方向更改后调用。您的容器 Activity 必须实现接口并接收方法调用。

    https://developer.android.com/guide/components/fragments.html#EventCallbacks

    【讨论】:

    • 不,我不能使用 Activity 作为监听器,因为我的 Fragment 有一个演示者,当我单击 DialogFragment 中的按钮时,我需要调用它的方法。
    • 你应该。您必须从活动重定向到给定的片段/演示者。或者使用 EventBus。
    • 那么就没有办法使用Fragment作为监听器了吗?
    • 不直接,不(欢迎来到复杂的碎片世界)
    • 有趣。您的解决方案严格来说是一对一的,但是如果您将标签作为对话框构造的参数,也有一些方法可以解决这个问题。我想知道是否有缺点,但对我来说似乎还可以。
    猜你喜欢
    • 2012-08-20
    • 1970-01-01
    • 1970-01-01
    • 2013-01-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多