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
相关产品推荐
相关产品推荐

