【问题标题】:Access from DialogFragment to host Activity's views从 DialogFragment 访问宿主 Activity 的视图
【发布时间】:2019-05-24 19:57:49
【问题描述】:

我遇到过这样的问题。在我的应用程序中,我有一个 Activity (MobileActivity),其中包含一些视图(Spinners、TextViews 和 Button)。当用户点击按钮时,我需要打开一个对话框(ConfirmDialog)。在这个对话框中,我需要从 MobileActivity 的视图中显示一些数据(参见下面的代码)。有时在 Play Console 中,我会看到带有 NullPointerException 的崩溃报告(我在代码中标记了该行)。 问题出在哪里?

谢谢!

我想,问题可能出在 Activity 的生命周期方法中。我尝试了接下来的操作:

  • 在模拟器上启动我的应用程序并打开 DialogFragment
  • 按下主页按钮
  • 在 adb 中,杀死了我的进程 (adb kill )
  • 从后台应用重新打开我的应用

它没有崩溃。那么,问题不在于后台吗?

来自 MobileActivity 的代码,它将打开我的 DialogFragment

ConfirmDialog newFragment = new ConfirmDialog();
newFragment.show(getFragmentManager(), "Confirmation"); 

来自 ConfirmDialog 的代码

    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {
        AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
        // Get the layout inflater
        LayoutInflater inflater = getActivity().getLayoutInflater();
            View v = null;
        Spinner s;
            v = inflater.inflate(R.layout.confirm_mobile_layout, null);
        builder.setView(v);
        //next row marked in stacktrace as problem row
        //Spinner with Id=acn_debit_mobile is placed on MobileActivity
        s = getActivity().findViewById(R.id.acn_debit_mobile);         
        Spinner b = getActivity().findViewById(R.id.biller_mobile);
            //other code
            return builder.create();
 }

还有来自 Play 控制台的堆栈跟踪

java.lang.RuntimeException: 
 at android.app.ActivityThread.performLaunchActivity (ActivityThread.java:2814)
 at android.app.ActivityThread.handleLaunchActivity (ActivityThread.java:2892)
 at android.app.ActivityThread.handleRelaunchActivity (ActivityThread.java:4763)
 at android.app.ActivityThread.-wrap18 (Unknown Source)
 at android.app.ActivityThread$H.handleMessage (ActivityThread.java:1621)
 at android.os.Handler.dispatchMessage (Handler.java:106)
 at android.os.Looper.loop (Looper.java:171)
 at android.app.ActivityThread.main (ActivityThread.java:6635)
 at java.lang.reflect.Method.invoke (Native Method)
 at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run (RuntimeInit.java:547)
 at com.android.internal.os.ZygoteInit.main (ZygoteInit.java:823)

Caused by: java.lang.NullPointerException: 
 at ua.grant.smart.ConfirmDialog.onCreateDialog (ConfirmDialog.java:121)
 at android.app.DialogFragment.onGetLayoutInflater (DialogFragment.java:406)
 at android.app.Fragment.performGetLayoutInflater (Fragment.java:1325)
 at android.app.FragmentManagerImpl.moveToState (FragmentManager.java:1279)
 at android.app.FragmentManagerImpl.moveFragmentToExpectedState (FragmentManager.java:1562)
 at android.app.FragmentManagerImpl.moveToState (FragmentManager.java:1623)
 at android.app.FragmentManagerImpl.dispatchMoveToState (FragmentManager.java:3032)
 at android.app.FragmentManagerImpl.dispatchActivityCreated (FragmentManager.java:2984)
 at android.app.FragmentController.dispatchActivityCreated (FragmentController.java:178)
 at android.app.Activity.performCreate (Activity.java:7090)
 at android.app.Activity.performCreate (Activity.java:7075)
 at android.app.Instrumentation.callActivityOnCreate (Instrumentation.java:1215)
 at android.app.ActivityThread.performLaunchActivity (ActivityThread.java:2767)

我添加了 onAttach 和 onDetach 方法来存储对我的主机 Activity 的引用(下面的代码),并在 ConfirmDialog 类的所有位置将 getActivity() 替换为 mActivity。能解决这个问题吗?

mActivity Activity;

@Override
public void onAttach(Activity activity) {
    super.onAttach(activity);
    mActivity = activity;
}

@Override
public void onDetach() {
    super.onDetach();
    mActivity = null;
}

【问题讨论】:

    标签: android android-dialogfragment


    【解决方案1】:

    在片段分离时保留活动实例并销毁它是避免NullPointerException的好方法

    mActivity Activity;
    
    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);
        mActivity = activity;
    }
    
    @Override
    public void onDetach() {
        super.onDetach();
        mActivity = null;
    }
    

    但您可能需要检查两件事。

    1. 为什么不对片段使用相同的方法,mActivityonCreateDialog 中的位置。顺便说一句,在进行任何交易之前,请检查 mActivity 是否为空。

    1. 使用yourDialogFragment.show() 显式运行此函数:

    ft.commit() 安排提交此事务。提交不会立即发生。它将被安排为主线程上的工作,以便在该线程下一次准备好时完成。所以我们无法确保任何事情,例如可能导致IllegalStateException

    怎么样:commitAllowingStateLoss()。但使用前请仔细阅读文档。看看this

    1. 你为什么不在onCreateView 增加视图? (您不必在onCreateDialog 中这样做)

    【讨论】:

    • 感谢您的回答!当然,我将使用 mActivity 而不是 getActivity(),但我可以确定它会帮助我在我的情况下避免 NullPointerException 吗?关于 IllegalStateException:我在其他地方遇到过这个问题。看起来也很奇怪:错误仅出现在一部手机中(上个月)。而且我也无法重现这个问题。
    • 为什么我应该在 onCreateView 中膨胀视图,而不是在 onCreateDialog 中?我从 developer.android.com 获取了这段代码,所以我确信它是正确的)
    • 对于您附加的日志,检查每个 getActivity() 的 null 可能会帮助您避免 NullPointerException
    • 是的,两者都有效,但默认情况下 onCreateView 会给你充气。您不必从ActivitygetLayoutInflaterstackoverflow.com/questions/13257038/…
    • 您确实可以同时覆盖两者,但是当您在创建对话框视图后尝试膨胀视图时就会出现问题。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-03-16
    • 1970-01-01
    • 2020-12-16
    相关资源
    最近更新 更多