【问题标题】:Android DialogFragment getActivity() is nullAndroid DialogFragment getActivity() 为空
【发布时间】:2014-03-18 20:47:27
【问题描述】:

我正在尝试创建一个对话框,在用户注销之前向用户显示倒计时。超时是从另一个活动设置的。

我写了以下代码:

import android.app.AlertDialog;
import android.app.Dialog;
import android.app.DialogFragment;
import android.content.DialogInterface;
import android.content.res.Resources;
import android.os.Bundle;

public class SessionInactivityDialog extends DialogFragment {

    public void setInactivityTimeout(long timeout) {
        Resources res = getActivity().getResources();
        String text = String.format(res.getString(R.string.iminent_logout_text), (timeout / 1000));
        ((AlertDialog)getDialog()).setMessage(text);
    }

    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {
        AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());

        builder.setTitle(R.string.iminent_logout);
        builder.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int id) {
                SessionActivity activity = (SessionActivity)getActivity();
                activity.resetTimer();
            }
        });

     return builder.create();
    }

}

用这些行调用对话框:

private void showIminentLogoutDialog(long timeout) {
    mInactivityDialog.show(getFragmentManager(), TAG);
    mInactivityDialog.setInactivityTimeout(timeout);
}

即使在对话框打开后设置了超时,setInactivityTimeout() 中的getActivity() 也是null

如何正确获取片段中的资源?

【问题讨论】:

    标签: android nullpointerexception android-alertdialog dialogfragment


    【解决方案1】:

    DialogFragment.show() 是异步的——DialogFragment 实际上并没有立即显示——它被发送到消息队列的末尾。我建议提供超时值作为参数,然后将其与标题一起设置在 onCreateDialog() 中。例如:

    public class SessionInactivityDialog extends DialogFragment {
        public static final String EXTRA_TIMEOUT = "timeout";
    
        public static SessionInactivityDialog newInstance(long timeout) {
            Bundle args = new Bundle();
            args.putLong(EXTRA_TIMEOUT, timeout);
            SessionInactivityDialog dialog = new SessionInactivityDialog();
            dialog.setArguments(args);
            return dialog;
        }
    
        @Override
        public Dialog onCreateDialog(Bundle savedInstanceState) {
            final SessionActivity activity = (SessionActivity) getActivity();
            final long timeout = getArguments().getLong(EXTRA_TIMEOUT);
            final String msg = activity.getString(R.string.imminent_logout_text, (timeout / 1000));
    
            AlertDialog.Builder builder = new AlertDialog.Builder(activity);
            builder.setTitle(R.string.imminent_logout);
            builder.setMessage(msg);
            builder.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int which) {
                    activity.resetTimer();
                }
            });
            return builder.create();
        }
    }
    

    然后你可以用:

    SessionInactivityDialog.newInstance(timeout)
                           .show(getFragmentManager(), TAG);
    

    我还建议为对话框创建一个与活动通信的接口,而不是添加对SessionActivity 的直接依赖(这样你就可以在任何活动中重复使用它,只要因为它实现了你的接口)。

    【讨论】:

    • 但是当我调用newInstance时,每次都会创建一个新的Dialog,我想更新超时时间。超时设置为每秒,因此用户必须关闭与调用活动打开的对话框一样多的对话框。如果我使用重用实例(例如单例对话框),这是否意味着任何其他缺点或者可以吗?
    • 我尝试了单例方法,但失败了。该片段已经处于活动状态,并且 setArguments 产生IllegalStateException。我该如何解决?我不想添加另一个CountdownTimer 只是为了刷新对话框中的文本。
    • 如果需要实时更新,那么Fragment 本身应该处理倒计时的逻辑,并且一旦定时器用完或者应该被重置就回调Activity。或者,您可以在显示对话框后在您的 Activity 中调用 getFragmentManager().executePendingTransactions(),然后您可以在知道 Fragment 已附加到 Activity 的情况下调用其方法。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-06-08
    • 1970-01-01
    • 1970-01-01
    • 2012-05-19
    • 2017-10-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多