{"record":{"id":"e2e724c0842aa6c9","repo":"scwang90/SmartRefreshLayout","slug":"defaultrefreshheadercreator-can-not-return-null","errorCode":null,"errorMessage":"DefaultRefreshHeaderCreator can not return null","messagePattern":"DefaultRefreshHeaderCreator can not return null","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"refresh-layout-kernel/src/main/java/com/scwang/smart/refresh/layout/SmartRefreshLayout.java","lineNumber":412,"sourceCode":"     * 2.做 Content 为空时的 TextView 提示\n     * 3.智能开启 嵌套滚动 NestedScrollingEnabled\n     * 4.初始化 主题颜色 和 调整 Header Footer Content 的显示顺序\n     */\n    @Override\n    protected void onAttachedToWindow() {\n        super.onAttachedToWindow();\n        mAttachedToWindow = true;\n\n        final View thisView = this;\n        // 在非编辑模式下，如果 onFinishInflate 初始化组件未成功，onAttachedToWindow 可以进行补充处理\n        if (!thisView.isInEditMode()) {\n\n            if (mRefreshHeader == null) {\n                if (sHeaderCreator != null) {\n                    RefreshHeader header = sHeaderCreator.createRefreshHeader(thisView.getContext(), this);\n                    //noinspection ConstantConditions\n                    if (header == null) {\n                        throw new RuntimeException(\"DefaultRefreshHeaderCreator can not return null\");\n                    }\n                    setRefreshHeader(header);\n                }\n            }\n            if (mRefreshFooter == null) {\n                if (sFooterCreator != null) {\n                    RefreshFooter footer = sFooterCreator.createRefreshFooter(thisView.getContext(), this);\n                    //noinspection ConstantConditions\n                    if (footer == null) {\n                        throw new RuntimeException(\"DefaultRefreshFooterCreator can not return null\");\n                    }\n                    setRefreshFooter(footer);\n                }\n            } else {\n                mEnableLoadMore = mEnableLoadMore || !mManualLoadMore;\n            }\n\n            if (mRefreshContent == null) {","sourceCodeStart":394,"sourceCodeEnd":430,"githubUrl":"https://github.com/scwang90/SmartRefreshLayout/blob/224db48f8af897a930b810a6b6fc55af8cef0d57/refresh-layout-kernel/src/main/java/com/scwang/smart/refresh/layout/SmartRefreshLayout.java#L394-L430","documentation":"In onAttachedToWindow(), if no header was set from XML or code (mRefreshHeader == null) and a global default header creator is registered via SmartRefreshLayout.setDefaultRefreshHeaderCreator(...), that creator returned null — which the library treats as a programming error and throws. The creator contract requires a non-null RefreshHeader; the @noinspection ConstantConditions comment shows the authors deliberately made this a hard failure.","triggerScenarios":"Registering sHeaderCreator with SmartRefreshLayout.setDefaultRefreshHeaderCreator((context, layout) -> null) — or a lambda whose body can return null on some branch (e.g. conditional instantiation that falls through) — and then attaching any SmartRefreshLayout to the window without an explicit header.","commonSituations":"Copy-pasting a creator stub that has no return yet; a creator that returns null conditionally (theme/AB test branch) and one branch was missed; migration to a different header class where the constructor was removed but the return statement still returns null; proguard/R8 stripping a header class so reflection-based creation yields null.","solutions":["Make the creator always return a non-null header, e.g. (context, layout) -> new ClassicsHeader(context).","If you do not want a default header, do not register a creator at all — remove the setDefaultRefreshHeaderCreator call.","Audit every return path of a multi-branch creator and end it with a guaranteed fallback header.","If a header class seems missing at runtime, check ProGuard/R8 keep rules for the header class used inside the creator."],"exampleFix":"// before\nSmartRefreshLayout.setDefaultRefreshHeaderCreator((context, layout) -> {\n    if (useMaterial) return new MaterialHeader(context);\n    return null; // crashes on attach\n});\n\n// after\nSmartRefreshLayout.setDefaultRefreshHeaderCreator((context, layout) -> {\n    if (useMaterial) return new MaterialHeader(context);\n    return new ClassicsHeader(context);\n});","handlingStrategy":"validation","validationCode":"// Exercise the creator once at startup so a null return fails loudly in your code, not at attach time\nDefaultRefreshHeaderCreator creator = (context, layout) -> buildHeader(context);\nRefreshHeader probe = creator.createRefreshHeader(context, null);\nif (probe == null) throw new IllegalStateException(\"Header creator must never return null\");\nSmartRefreshLayout.setDefaultRefreshHeaderCreator(creator);","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Treat DefaultRefreshHeaderCreator as non-nullable-by-contract: end every creator with an unconditional 'return new ClassicsHeader(context);' style fallback.","Do not register a creator if you set headers per-layout in XML or code.","Add ProGuard keep rules for header classes referenced inside creators.","Cover creators with a unit test asserting non-null return on all branches."],"tags":["android","smartrefreshlayout","null-return","callback-contract","configuration"],"backgroundTag":null,"analyzedSha":"224db48f8af897a930b810a6b6fc55af8cef0d57","analyzedAt":"2026-08-14T10:09:28.455Z","schemaVersion":2},"datasetVersion":"2026-08-14T10:17:34.591Z"}