【问题标题】:Kotlin for Android: setting a Google Maps marker image to a URLKotlin for Android:将 Google 地图标记图像设置为 URL
【发布时间】:2020-12-09 00:15:14
【问题描述】:

我想在由 Android Kotlin 应用程序显示的 Google 地图上设置一个标记,作为我选择的 URL。很明显,获取 URL 内容需要在 UI 线程之外完成,而协程是这里的方法,所以我想运行几行代码来获取 URL 并将其放入内部的 BitmapDescription 对象中一个协程,然后使用该BitmapDescriptionMarker 对象上调用setIcon 以设置自定义图像。

我已经有一个Marker 和一个网址。所以我尝试了这个:

    uiScope.launch(Dispatchers.IO) { // not sure this is the best way to launch in IO
        val furl = URL(myURL)
        val bm = BitmapFactory.decodeStream(furl.openConnection().getInputStream())
        val bd = BitmapDescriptorFactory.fromBitmap(bm)
        uiScope.launch(Dispatchers.Main) { // go back to UI thread; this crashes
            marker.setIcon(bd)
        }
    }

这显然是不对的,因为它会崩溃。据我所知,获取 URL 并创建 BitmapDescriptor 似乎工作正常;一旦我有了BitmapDescriptor,我如何用它调用marker.setIcon

【问题讨论】:

    标签: android google-maps kotlin kotlin-coroutines kotlin-android-extensions


    【解决方案1】:

    虽然您说获取图像并创建BitmapDescriptor 似乎工作正常,但我几乎可以说使用URL 连接自己做是不对的。获取和解码图像的过程可能涉及许多无法以这种方式处理的可能错误。最好将此责任以及线程切换委托给可靠的工具,例如Glide

    让我们在kotlin 文件中使用GlideMarker 编写一个扩展函数:

    ExtensionFunctions.kt

    import android.content.Context
    import android.graphics.Bitmap
    import com.bumptech.glide.Glide
    import com.bumptech.glide.load.DataSource
    import com.bumptech.glide.load.engine.GlideException
    import com.bumptech.glide.request.RequestListener
    import com.bumptech.glide.request.target.Target
    import com.google.android.gms.maps.model.BitmapDescriptorFactory
    import com.google.android.gms.maps.model.Marker
    
    fun Marker.loadIcon(context: Context, url: String?) {
        Glide.with(context)
            .asBitmap()
            .load(url)
            .error(R.drawable.default_marker) // to show a default icon in case of any errors
            .listener(object : RequestListener<Bitmap> {
                override fun onLoadFailed(
                    e: GlideException?,
                    model: Any?,
                    target: Target<Bitmap>?,
                    isFirstResource: Boolean
                ): Boolean {
                    return false
                }
    
                override fun onResourceReady(
                    resource: Bitmap?,
                    model: Any?,
                    target: Target<Bitmap>?,
                    dataSource: DataSource?,
                    isFirstResource: Boolean
                ): Boolean {
                    return resource?.let {
                        BitmapDescriptorFactory.fromBitmap(it)
                    }?.let {
                        setIcon(it); true
                    } ?: false
                }
            }).submit()
    }
    

    现在。只需通过标记对象调用它以异步加载图像就足够了:

    marker.loadIcon(context, url)
    

    【讨论】:

    • 是的,一大堆建议归结为“为此使用 Glide”,而我正朝着这个方向倾斜。我不愿意向应用程序添加另一个依赖项,但这可能是最简单的方法;感谢您的指点和工作示例!
    猜你喜欢
    • 2019-03-30
    • 2018-11-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-27
    • 2014-12-22
    • 1970-01-01
    相关资源
    最近更新 更多