0

サーバーが送信したサムネイルを編集し、それらを Google GroundOverlay としてレンダリングするコードのセクションを構築する際に問題が発生しています。

この問題は、Kotlin コルーチンに起因しているようです。まず、Google のドキュメントによると、グラウンド オーバーレイはメイン スレッドで作成する必要があります。それらの作成をメイン スレッドから実行すると、致命的なエラーが発生します。したがって、これらの GroundOverlays をメイン スレッドで作成するようにしました。ただし、メインからスレッドにビットマップを作成しようとすると、オーバーレイがまったく表示されないようです。

class BarreMapFragment : Fragment(),
    GoogleMap.OnCameraIdleListener,
    GoogleMap.OnCameraMoveCanceledListener,
    GoogleMap.OnCameraMoveListener,
    GoogleMap.OnCameraMoveStartedListener,
    OnMapReadyCallback {

        //Main handler for google map/item styling
        googleMapHandler = GoogleMapHandler(gMap!!, activity!!.applicationContext, DefaultTheme, lifecycle.coroutineScope)


.    .    .

open class GoogleMapHandler(val gMap: GoogleMap,
                            val context: Context,
                            val mapThemeInstructions: MapThemeInstructions,
                            val coroutineScope: CoroutineScope
) {

fun updateActiveUserAvatarPosition(position: LatLng) {

        if (mActiveUserAvatar == null) {

            coroutineScope.launch {
                mActiveUserAvatar = mapObjectFactory.factory(
                    MapObject(
                        latitude = position.latitude,
                        longitude = position.longitude,
                        objectId = "SELF_AVATAR",
                        objectType = MapObjectType.USER_AVATAR,
                        timestamp = System.currentTimeMillis(),
                        weight = 20.toFloat()
                    ), getOverlayWidthByZoom(dpScreenWidth, gMap.cameraPosition.target, gMap.cameraPosition.zoom)) as RenderedUserAvatarItem
            }

        }

        mActiveUserAvatar?.updatePosition(position)
    }
    suspend fun factory(mapObject: MapObject, diameter: Float) : RenderedMapItem {

        overlayDiameter = diameter

        val item = RenderedUserAvatarItem(
            mapObject,
            buildOverlay(mapObject)
        )

        return item
    }

    @MainThread
    private suspend fun buildOverlay(mapObject: MapObject) : GroundOverlay {

        Log.d("UserOverlay", "I was called.")
        //Get the bitmap from the resources
        //TODO:  We can do more with this later...  Like custom avatars



        //val bitmap = BitmapFactory.decodeResource(context.resources, R.drawable.ic_user_avatar)
        val bitmap =  withContext(Dispatchers.Default) {
            async {
                val d: Drawable = context.getDrawable(R.drawable.ic_user_avatar)!!
                val bitmap : Bitmap = drawableToBitmap(d)!!
                bitmap
            }
        }.await()

        //val d: Drawable = context.getDrawable(R.drawable.ic_user_avatar)!!
        //val bitmap : Bitmap = drawableToBitmap(d)!!

        Log.d(TAG, "bitmap = " + bitmap.toString())

        //Make bitmap descriptor
        val descriptor = BitmapDescriptorFactory.fromBitmap(bitmap)

        val overlayOptions = GroundOverlayOptions().image(descriptor)

        //Position and size of groundoverlay
        overlayOptions.position(LatLng(mapObject.latitude, mapObject.latitude) , overlayDiameter)

        //Add the overlay to the map, get a handle and save it to public Overlay list
        val mOverlay = gMap.addGroundOverlay(overlayOptions)

        //Store the moment information in the overlay tag
        mOverlay.tag = mapObject.objectId

        return mOverlay
    }

suspend 関数は、メイン スレッドから呼び出されます。今、

        val bitmap =  withContext(Dispatchers.Unconfined) {
            async {
                val d: Drawable = context.getDrawable(R.drawable.ic_user_avatar)!!
                val bitmap : Bitmap = drawableToBitmap(d)!!
                bitmap
            }
        }.await()

および上記のコメントアウトされたセクション (非同期を使用せずに)

        val d: Drawable = context.getDrawable(R.drawable.ic_user_avatar)!!
        val bitmap : Bitmap = drawableToBitmap(d)!!

どちらも問題なく GroundOverlay を生成します。Dispatchers.Unconfined を他のものに変更すると、問題が発生します。Dispatchers.Main でさえ、GroundOverlay がマップに表示されません。GroundOverlays が作成されました。ログ ステートメントで確認しました。それらの透明性は、可視性と同様に期待されています。問題はビットマップにあるようです。await() の仕組みを理解していないと思います。ビットマップが返されて準備が整うまで、サスペンド機能を一時停止すると考えました。

これは、エラーを特定するための簡略化されたコードです。各サムネイルは場所と時刻に応じてスタイルが調整されるため、Dispatchers.Default でこれを行う必要があります。この処理をメイン スレッドで行うと、UI での処理が難しくなります。

4

0 に答える 0