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

图片上传成功却报NullPointerException错误(AsyncTask相关)

图片上传成功后应用触发空指针异常

我将图片上传至网站,上传操作成功完成,但应用出现致命错误。怀疑是AsyncTask执行时机过早导致的,目前已将SDK版本从30升级至32,使用的UCrop版本为2.2.5。

错误日志

FATAL EXCEPTION: main
 Process: com.myappname.dating, PID: 17170
 java.lang.NullPointerException: Parameter specified as non-null is null: method kotlin.jvm.internal.Intrinsics.checkNotNullParameter,
 parameter avatar
     at com.myappname.dating.ui.home.profileImageUploading.UserImageCropActivity$UpdateTaskA.<init>(Unknown
 Source:7)
     at com.myappname.dating.ui.home.profileImageUploading.UserImageCropActivity$updateAvaterp$1.onResponse(UserImageCropActivity.kt:190)

问题分析

空指针异常出现在UpdateTaskA的构造函数中:你把avatar声明为非空的String类型,但实际传入的值是null,触发了Kotlin的空安全检查。

具体原因是在updateAvaterp的onResponse回调里,你用!!强制获取response.body()!!.picurl——即使接口返回response.isSuccessful为true,response.body()或者picurl字段仍可能为null,直接强制取值就会导致传入UpdateTaskA的avatar参数为空。

另外,你使用AsyncTask.execute().get()会阻塞主线程,容易造成UI卡顿甚至ANR,这也是不推荐的写法。

解决方案

1. 处理接口返回的空值

在使用接口返回数据前先做空值判断,避免传入null到UpdateTaskA:

override fun onResponse(call: Call<ProfileStatus>, response: Response<ProfileStatus>) {
    if (response.isSuccessful) {
        val profileStatus = response.body()
        val avatarUrl = profileStatus?.picurl
        if (!avatarUrl.isNullOrEmpty()) {
            UpdateTaskA(this@UserImageCropActivity, avatarUrl, userResponse.id).execute()
            Toast.makeText(applicationContext, "Profile Upload Successfully", Toast.LENGTH_SHORT).show()
            finish()
        } else {
            Toast.makeText(applicationContext, "上传成功但未获取到头像URL", Toast.LENGTH_SHORT).show()
            uploadBtn.isClickable = true
            uploadBtn.setBackgroundColor(Color.parseColor("#2196f3"))
        }
    } else {
        Toast.makeText(applicationContext, "上传失败,接口返回异常", Toast.LENGTH_SHORT).show()
        uploadBtn.isClickable = true
        uploadBtn.setBackgroundColor(Color.parseColor("#2196f3"))
    }
}

2. 修复UpdateTaskA的空安全

如果avatar存在为空的可能,将构造函数参数改为可空类型,并在内部处理:

class UpdateTaskA(var context: UserImageCropActivity, var avatar: String?, var id : Int) :
    AsyncTask<Void, Void, Boolean>() {
    override fun doInBackground(vararg params: Void?): Boolean {
        avatar?.let {
            val imageAvatar = CommonUtil.convertToString64(it)
            imageAvatar?.let { encodedAvatar ->
                context.mCrushDataBase!!.crushDao().updateAvatar(encodedAvatar, id)
            }
        }
        return true
    }

    override fun onPostExecute(bool: Boolean?) {
        // 可添加更新完成后的逻辑
    }
}

3. 替换废弃的AsyncTask(可选)

AsyncTask已被官方废弃,推荐用Coroutines执行后台任务,避免主线程阻塞:

// 在Activity中声明CoroutineScope
private val scope = CoroutineScope(Dispatchers.Main)

// 替换原来的AsyncTask调用
scope.launch {
    withContext(Dispatchers.IO) {
        avatar?.let {
            val imageAvatar = CommonUtil.convertToString64(it)
            imageAvatar?.let { encodedAvatar ->
                mCrushDataBase!!.crushDao().updateAvatar(encodedAvatar, userResponse.id)
            }
        }
    }
    Toast.makeText(applicationContext, "Profile Upload Successfully", Toast.LENGTH_SHORT).show()
    finish()
}

4. 修复主线程阻塞问题

把getDataTask的阻塞调用改为非阻塞方式:

// 替换原来的userResponse = getDataTask(this).execute().get()
scope.launch {
    userResponse = withContext(Dispatchers.IO) {
        val listOfdata = mCrushDataBase!!.crushDao().getData()
        listOfdata[0]
    }
}

内容的提问来源于stack exchange,提问作者Sandeep Kumar

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 01:35:22