█ 【安卓学习之常见问题】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"去掉
⚡️复制时,需要注意细节
█ 相关资料
提示:这里是参考的相关文章
提示:转载请注明出处:
https://blog.csdn.net/ljb568838953/article/details/112762589