You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android使用Glide加载图片报NullPointerException如何解决?

问题日志
2022-06-20 13:19:27.605 20830-20830/com.example.moveapplication E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.moveapplication, PID: 20830
java.lang.NullPointerException: Argument must not be null
    at com.bumptech.glide.util.Preconditions.checkNotNull(Preconditions.java:29)
    at com.bumptech.glide.util.Preconditions.checkNotNull(Preconditions.java:23)
    at com.bumptech.glide.RequestBuilder.into(RequestBuilder.java:768)
    at com.example.moveapplication.activities.MainActivity.openBottomSheetDialog$lambda-2(MainActivity.kt:100)
    at com.example.moveapplication.activities.MainActivity.$r8$lambda$acEx44X-0qqDdGYpms4KzfGag5A(Unknown Source:0)
    at com.example.moveapplication.activities.MainActivity$$ExternalSyntheticLambda3.onSuccess(Unknown Source:15)
    at com.google.android.gms.tasks.zzm.run(com.google.android.gms:play-services-tasks@@18.0.1:1)
    at android.os.Handler.handleCallback(Handler.java:883)
    at android.os.Handler.dispatchMessage(Handler.java:100)
    at android.os.Looper.loop(Looper.java:214)
    at android.app.ActivityThread.main(ActivityThread.java:7356)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:930)
根因定位

报错触发点为Glide加载代码的.into(uImage)行,核心原因有2个:

  1. 控件获取逻辑错误:sheetIvProfileImage等控件属于BottomSheet弹窗的独立布局R.layout.bottom_sheet_dialog,不属于MainActivity自身的布局文件,直接调用Activity的findViewById无法找到对应控件,返回null。Glide的into()方法强制要求传入的ImageView参数非空,直接触发空指针异常。
  2. 代码执行顺序错乱:原代码先发起Firebase异步数据请求,再初始化弹窗、加载弹窗布局,异步请求回调时机不固定,大概率在弹窗布局未完成加载时就执行控件赋值、图片加载逻辑,进一步加剧空指针风险。另外原代码遗漏了bottomSheetDialog.show()调用,即使修复空指针问题,弹窗也无法正常展示。
修复方案
  • 调整代码执行顺序:先完成BottomSheetDialog初始化、弹窗布局inflate操作,再发起Firebase数据请求
  • 所有弹窗内的控件,统一从inflate得到的bottomSheetView对象上调用findViewById获取,禁止使用Activity的findViewById查找弹窗布局内的控件
  • 数据回调中增加多层空判断:同时判断document存在、ownerModel非空、图片地址非空、控件实例非空后,再执行Glide加载和文本赋值逻辑
  • 初始化完成后调用show()方法展示弹窗

修复后完整代码如下:

private fun openBottomSheetDialog(position: Int) {
    val publisher = posts[position].publisher
    // 先初始化弹窗、加载弹窗布局
    val bottomSheetDialog = BottomSheetDialog(this, R.style.BottomSheetDialogTheme)
    val bottomSheetView = LayoutInflater.from(this).inflate(
        R.layout.bottom_sheet_dialog,
        findViewById(R.id.bottomSheet)
    )
    // 从弹窗布局对象上获取控件,不要用Activity的findViewById
    val uImage = bottomSheetView.findViewById<ImageView>(R.id.sheetIvProfileImage)
    val uNumber = bottomSheetView.findViewById<TextView>(R.id.sheetTvOwnerNumber)
    val uEmail = bottomSheetView.findViewById<TextView>(R.id.tvOwnerEmail)
    val uAbout = bottomSheetView.findViewById<TextView>(R.id.tvOwnerAbout)
    val uTitle = bottomSheetView.findViewById<TextView>(R.id.sheetTvOwnerTitle)

    // 布局和控件初始化完成后再请求数据
    val ownersRef = FirebaseFirestore.getInstance().collection("owners").document(publisher)
    ownersRef.get().addOnSuccessListener { document ->
        val ownerModel = document.toObject(Owner::class.java)
        // 非空判断后再操作
        ownerModel?.let { model ->
            uTitle.text = model.username
            uNumber.text = model.phoneNumber
            uEmail.text = model.email
            uAbout.text = model.about
            // 图片地址非空再加载
            if (!model.profileImage.isNullOrEmpty()) {
                Glide.with(this)
                    .load(model.profileImage)
                    .into(uImage)
            }
        }
    }

    // 绑定布局、展示弹窗
    bottomSheetDialog.apply {
        setContentView(bottomSheetView)
        setCancelable(true)
        show()
    }
}

额外优化点:如果Firebase请求耗时较长,用户提前关闭弹窗会导致Activity销毁,Glide加载可能出现内存泄漏,可在addOnSuccessListener中增加判断Activity是否处于销毁状态的逻辑,规避生命周期关联问题。

内容的提问来源于stack exchange,提问作者Sam Kabiru

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.29 11:39:41