【安卓学习之常见问题】DialogFragment.show抛错NestedScrollView.setFocusable(boolean)‘ on a null object reference

█ 【安卓学习之常见问题】DialogFragment.show抛错NestedScrollView.setFocusable(boolean)’ on a null object reference


█ 系列文章目录

提示:这里是收集了无人机的相关文章


█ 文章目录


█ 读前说明

  • 本文通过学习别人写demo,学习一些课件,参考一些博客,’学习相关知识,如果涉及侵权请告知
  • 本文只简单罗列相关的代码实现过程
  • 涉及到的逻辑以及说明也只是简单介绍,主要当做笔记,了解过程而已

█ 项目场景

  • Android对话框通常通过Dialog和基于Fragment的DialogFragment来显示。
  • AlertDialog:简单但容易出现bug、内存泄漏等等问题。
  • DialogFragment:Google推荐,DialogFragment帮你管理Dialog的生命周期,不需要手动dismiss。
  • 区别:
    • 1.在手机配置变化(如横竖屏切换),导致Activity销毁需要重新创建时,DialogFragment的对话框将会由FragmentManager自动重建,AlertDialog实现的对话框不会。
    • 2.DialogFragment还拥有fragment的优点,即可以在一个Activity内部实现回退(因为FragmentManager会管理一个回退栈)。
    • 3.一般都用标配的 PrefrenceFragment 写配置系统。然后以 Activity 为容器显示PrefrenceFragment。

█ 问题描述:

在Fragment中执行 自定义的DialogFragment中show时,报错:

  • 执行代码
  YesNoDialogFragment ynd = YesNoDialogFragment.newInstance(context, "提示",
                 "确认提交?");
  ynd.show(getChildFragmentManager());
  • 异常报错
2021-01-18 09:51:07.256 5868-5868/com.xxx.xxx.debug E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.xxx.xxx.debug, PID: 5868
    java.lang.NullPointerException: Attempt to invoke virtual method 'void androidx.core.widget.NestedScrollView.setFocusable(boolean)' on a null object reference
        at androidx.appcompat.app.AlertController.setupContent(AlertController.java:720)
        at androidx.appcompat.app.AlertController.setupView(AlertController.java:486)
        at androidx.appcompat.app.AlertController.installContent(AlertController.java:233)
        at androidx.appcompat.app.AlertDialog.onCreate(AlertDialog.java:279)
        at android.app.Dialog.dispatchOnCreate(Dialog.java:403)
        at android.app.Dialog.show(Dialog.java:302)
        at androidx.fragment.app.DialogFragment.onStart(DialogFragment.java:529)
        at androidx.fragment.app.Fragment.performStart(Fragment.java:2730)
        at androidx.fragment.app.FragmentStateManager.start(FragmentStateManager.java:365)
        at androidx.fragment.app.FragmentManager.moveToState(FragmentManager.java:1194)
        at androidx.fragment.app.FragmentManager.moveToState(FragmentManager.java:1356)
        at androidx.fragment.app.FragmentManager.moveFragmentToExpectedState(FragmentManager.java:1434)
        at androidx.fragment.app.FragmentManager.moveToState(FragmentManager.java:1497)
        at androidx.fragment.app.BackStackRecord.executeOps(BackStackRecord.java:447)
        at androidx.fragment.app.FragmentManager.executeOps(FragmentManager.java:2169)
        at androidx.fragment.app.FragmentManager.executeOpsTogether(FragmentManager.java:1992)
        at androidx.fragment.app.FragmentManager.removeRedundantOperationsAndExecute(FragmentManager.java:1947)
        at androidx.fragment.app.FragmentManager.execPendingActions(FragmentManager.java:1849)
        at androidx.fragment.app.FragmentManager$4.run(FragmentManager.java:413)
        at android.os.Handler.handleCallback(Handler.java:790)
        at android.os.Handler.dispatchMessage(Handler.java:99)
        at android.os.Looper.loop(Looper.java:164)
        at android.app.ActivityThread.main(ActivityThread.java:6518)
        at java.lang.reflect.Method.invoke(Native Method)

在这里插入图片描述


█ 原因分析:

1.自定义DialogFragment代码是从另一个自定义DialogFragment代码复制过来

⚡️原代码可以正常显示,而新自定义不行,很有可能就是xml的布局问题导致的。

2.查看at androidx.appcompat.app.AlertController.setupContent(AlertController.java:720)

⚡️androidx.appcompat.app.AlertController.setupContent()中执行NestedScrollView.setFocusable(boolean) 抛出NullPointerException,mScrollView是空指针,说明R.id.scrollView找不到

    private void setupContent(ViewGroup contentPanel) {
        mScrollView = (NestedScrollView) mWindow.findViewById(R.id.scrollView);
        mScrollView.setFocusable(false);
        mScrollView.setNestedScrollingEnabled(false);

        。。。。。。
    }

在这里插入图片描述

3.查看at androidx.appcompat.app.AlertController.setupView(AlertController.java:486)

⚡️setupContent(contentPanel);这句中的contentPanel有问题,
⚡️contentPanel的默认值defaultContentPanel肯定里面是包含R.id.scrollView,所以应该就是自义定的xml中对应的customContentPanel没有R.id.scrollView
⚡️customContentPanel是来自R.id.contentPanel,查看DialogFragment自定义的xml文件确实有R.id.contentPanel却没有R.id.scrollView

 private void setupView() {
        final View parentPanel = mWindow.findViewById(R.id.parentPanel);
        final View defaultTopPanel = parentPanel.findViewById(R.id.topPanel);
        final View defaultContentPanel = parentPanel.findViewById(R.id.contentPanel);
        final View defaultButtonPanel = parentPanel.findViewById(R.id.buttonPanel);

        // Install custom content before setting up the title or buttons so
        // that we can handle panel overrides.
        final ViewGroup customPanel = (ViewGroup) parentPanel.findViewById(R.id.customPanel);
        setupCustomContent(customPanel);

        final View customTopPanel = customPanel.findViewById(R.id.topPanel);
        final View customContentPanel = customPanel.findViewById(R.id.contentPanel);
        final View customButtonPanel = customPanel.findViewById(R.id.buttonPanel);

        // Resolve the correct panels and remove the defaults, if needed.
        final ViewGroup topPanel = resolvePanel(customTopPanel, defaultTopPanel);
        final ViewGroup contentPanel = resolvePanel(customContentPanel, defaultContentPanel);
        final ViewGroup buttonPanel = resolvePanel(customButtonPanel, defaultButtonPanel);

        setupContent(contentPanel);
        setupButtons(buttonPanel);
        setupTitle(topPanel);
        
        。。。。。。
    }

在这里插入图片描述

4.查看复制过来的原代码DialogFragment

⚡️自定义的xml文件确实有R.id.contentPanel,也有R.id.scrollView,所以没报错

<?xml version="1.0" encoding="utf-8"?>

<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/contentPanel"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <androidx.core.widget.NestedScrollView
        android:id="@+id/scrollView"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:paddingTop="2dip"
        android:paddingBottom="12dip"
        android:paddingStart="14dip"
        android:paddingLeft="14dp"
        android:paddingRight="10dp"
        android:paddingEnd="10dip"
        android:overScrollMode="ifContentScrolls">

        <TextView
            android:id="@+id/yes_no_message"
            style="?android:attr/textAppearanceMedium"
            tools:text="This is a test"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:padding="5dip"/>
    </androidx.core.widget.NestedScrollView>

    <CheckBox
        android:id="@+id/yes_no_dont_show_checkbox"
        android:visibility="gone"
        tools:visibility="visible"
        android:layout_marginLeft="15dp"
        android:layout_marginRight="15dp"
        android:layout_marginBottom="12dp"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="@string/label_yes_no_dialog_dont_show"/>
</LinearLayout>

█ 解决方案:

将xml文件中的android:id="@+id/contentPanel"去掉

⚡️复制时,需要注意细节


█ 相关资料

提示:这里是参考的相关文章

  1. DialogFragment与一般的AlertDialog的区别在哪里? - 知乎

提示:转载请注明出处:
https://blog.csdn.net/ljb568838953/article/details/112762589

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值