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

Kotlin使用Picasso将URL转Bitmap时报主线程调用异常如何解决

异常根因

你遇到的java.lang.IllegalStateException: Method call should not happen from the main thread.异常,是因为Picasso.with(context).load(user_URL[i]).get()是同步阻塞方法,内部会执行网络请求、本地IO读写这类耗时操作,而Android系统禁止在主线程(UI线程)执行耗时任务,避免阻塞UI渲染甚至触发ANR(应用无响应),因此调用时直接抛出了该异常。


解决方案

提供两种可行的修复方式,可根据你的业务场景选择:

方案1:使用Picasso自带异步回调加载(推荐,无需额外依赖)

放弃同步get()写法,改用异步回调加载图片,加载完成后再更新Marker图标,Picasso的回调默认执行在主线程,无需额外做线程切换:

user_URL = maprepo.returnImage()
latitude = maprepo.returnLatitude()
longitude = maprepo.returnLongitude()

for (i in 0 until latitude.size) {
    val latLng = LatLng(latitude[i], longitude[i])
    // 先添加带占位图的Marker,避免加载过程中空白
    val marker = googleMap.addMarker(MarkerOptions()
        .position(latLng)
        .title("")
        // 可自定义占位图标,也可以用系统默认Marker
        .icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_BLUE))
    )

    // 异步加载图片
    Picasso.with(context)
        .load(user_URL[i])
        // 可选:设置加载失败/占位图
        .placeholder(R.drawable.default_marker)
        .error(R.drawable.load_fail_marker)
        .into(object : Target {
            override fun onBitmapLoaded(bitmap: Bitmap?, from: Picasso.LoadedFrom?) {
                bitmap ?: return
                // 加载完成后更新Marker图标
                marker?.setIcon(BitmapDescriptorFactory.fromBitmap(bitmap))
            }

            override fun onBitmapFailed(e: java.lang.Exception?, errorDrawable: Drawable?) {
                // 图片加载失败后的自定义处理逻辑
            }

            override fun onPrepareLoad(placeHolderDrawable: Drawable?) {
                // 图片开始加载前的处理逻辑,可选
            }
        })
}

注意:如果使用的是Picasso 2.71828及以上版本,Picasso.with(context)需要替换为Picasso.get()。


方案2:使用Kotlin协程执行同步加载逻辑

如果你需要保留同步get()的写法,可以借助Kotlin协程把耗时操作放到IO线程执行,加载完成后自动切回主线程更新UI:

// 注意:lifecycleScope需要引入AndroidX lifecycle-runtime-ktx依赖,作用域和页面生命周期绑定
lifecycleScope.launch {
    user_URL = maprepo.returnImage()
    latitude = maprepo.returnLatitude()
    longitude = maprepo.returnLongitude()

    for (i in 0 until latitude.size) {
        // 子线程执行图片加载耗时操作
        val bitmap = withContext(Dispatchers.IO) {
            Picasso.with(context).load(user_URL[i]).get()
        }
        // 主线程添加Marker
        val makerOptions = MarkerOptions()
            .position(LatLng(latitude[i], longitude[i]))
            .title("")
            .icon(BitmapDescriptorFactory.fromBitmap(bitmap))
        googleMap.addMarker(makerOptions)
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.03 02:27:02