Kotlin使用Picasso将URL转Bitmap解决Google Maps标记类型不匹配与空指针问题
问题根源
getBitmap方法存在异步逻辑同步返回的核心错误:Picasso加载图片是子线程异步执行,into回调还没触发时就直接返回了初始值null,是NPE的主要诱因。- Kotlin空安全校验限制:可空类型
Bitmap?无法直接传入要求非空参数的fromBitmap方法,触发类型不匹配错误。
修复方案
1. 调整Bitmap加载逻辑,改用回调接收结果
不要试图实现同步返回Bitmap的方法,改为异步加载完成后回调通知:
private fun loadBitmap(url: String, onLoadFinish: (Bitmap?) -> Unit) { Picasso.get().load(url).into(object : com.squareup.picasso.Target { override fun onBitmapLoaded(bitmap: Bitmap?, from: Picasso.LoadedFrom?) { onLoadFinish(bitmap) } override fun onPrepareLoad(placeHolderDrawable: Drawable?) {} override fun onBitmapFailed(e: Exception?, errorDrawable: Drawable?) { onLoadFinish(null) } }) }
2. 调整Marker创建逻辑,先创建再更新图标
先添加带默认占位图的Marker,图片加载完成后再动态更新图标,同时做空判断兼容加载失败场景:
private fun otherUserMaker(googleMap: GoogleMap) { val latitude = maprepo.returnLatitude() val longitude = maprepo.returnLongitude() val user_URL = maprepo.returnImage() // 先校验三个列表长度一致,避免下标越界 val count = minOf(latitude.size, longitude.size, user_URL.size) for (i in 0 until count) { // 先添加Marker,可设置本地默认图标避免加载前空窗 val marker = googleMap.addMarker( MarkerOptions() .position(LatLng(latitude[i], longitude[i])) .title("") .icon(BitmapDescriptorFactory.fromResource(R.drawable.default_marker)) ) // 异步加载图片,加载成功后更新图标 loadBitmap(user_URL[i]) { bitmap -> bitmap?.let { validBmp -> marker?.setIcon(BitmapDescriptorFactory.fromBitmap(validBmp)) } } } }
3. 修复maprepo方法的返回值声明错误
你原有的returnImage方法缺少泛型声明,修正如下:
fun returnImage(): MutableList<String> { return photoUrl }
可选优化
- 加载失败时可以返回默认Bitmap,保证所有Marker都有图标:在
loadBitmap的onBitmapFailed回调里传入本地drawable转成的Bitmap即可。 - 可以给Picasso添加尺寸裁剪逻辑,避免加载过大图片占用内存:
Picasso.get().load(url).resize(100, 100).centerCrop().into(...),尺寸可根据Marker的实际大小调整。 - 若出现Target被GC回收导致加载无回调的问题,可以用全局HashMap持有Target引用,加载完成后再移除。
内容的提问来源于stack exchange,提问作者jyk
相关产品推荐
相关产品推荐

