Upgrade to Pro — share decks privately, control downloads, hide ads and more …

nacatl_slide_02_MapView_in_Recycler_view.pdf

nacatl
March 18, 2019
280

 nacatl_slide_02_MapView_in_Recycler_view.pdf

nacatl

March 18, 2019
Tweet

Transcript

  1. Copyright 2018 Studyplus, Inc. All Rights Reserved.
    MapView in RecyclerView
    つまずいた話
    Yuzuru Nakashima / Studyplus Inc.
    2019.03.18 @ Otemachi.apk #02

    View full-size slide

  2. 自己紹介
    ✎ なかてぃる
    affinity_robots
    nacatl
    ✎ スタディプラスのAndroidエンジニア
    ✎ 趣味: Magic the Gathering

    View full-size slide

  3. 目次
    ✎ GoogleMapAPI
    ✎ したかったこと
    ✎ うまくいったこと
    ✎ つまずいたこと

    View full-size slide

  4. GoogleMapPlatformAPI
    MapFragment? MapView?

    View full-size slide

  5. GoogleMapPlatformAPI
    GoogleMapを表示するViewとFragmentを提供
    - FragmentはLifeCycleの管理が楽(Viewだと面倒)
    - useViewLifecycleInFragment(true)
    - SupportLibrary版のSupportMapFragmentがある
    - LiteModeで表示すると単にbitmap表示するだけで軽い
    - 開発チームはオーストラリア(余談)

    View full-size slide

  6. したかったこと
    What is want to do?

    View full-size slide

  7. したかったこと
    大学のキャンパス一覧を
    RecyclerViewで実装したかった

    View full-size slide

  8. したかったこと
    - 既存からのリファクタリング
    - 不要なカスタムビュー撤廃
    - ButterKnife -> DataBinding
    - Java -> Kotlin (つい最近Javaを超えた!!)
    - なんか突っかかる(UIスレッドで色々してる?)
    - MapView -> MapFragmentにしてLifeCycle処理任せる

    View full-size slide

  9. うまくいったこと
    Success

    View full-size slide

  10. うまくいったこと
    - 突っかかりの解消
    カメラ位置の移動のために、GeoCoderを使って住所文字列から
    Map用のAddress クラスを取得する必要がある
    ここが遅いのにアイテム表示ごとにやってたから突っかかる
    -> Progress回しつつ初めに全アイテム分取得しておく
    RecyclerItemは住所文字列ではなくAddressを持つ

    View full-size slide

  11. うまくいったこと
    RecyclerViewのサイクルに合わせた表示処理
    - onCreateViewHolderでgetMap
    - onBindingViewHolderでmoveCamera
    - onViewRecycledでclear
    参考:
    https://github.com/googlemaps/android-samples/blob/master/ApiDemos/java/app/s
    rc/main/java/com/example/mapdemo/LiteListDemoActivity.java

    View full-size slide

  12. うまくいったこと
    RecyclerViewのサイクルに合わせた表示処理
    - onCreateViewHolderでgetMap
    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) =
    MapItemViewHolder(parent.inflate(viewType)).also { holder ->
    if (holder.binding is ListItemMapBinding) {
    holder.binding.campusMap.onCreate(null)
    holder.binding.campusMap.getMapAsync { map ->
    MapsInitializer.initialize(holder.itemView.context.applicationContext)
    mapType = GoogleMap.MAP_TYPE_NORMAL
    }
    }
    }

    View full-size slide

  13. うまくいったこと
    RecyclerViewのサイクルに合わせた表示処理
    - onBindViewHolderでmoveCamera
    override fun onBindViewHolder(holder: MapViewHolder, position: Int) {
    val mapListItem = getItem(position)
    holder.binding?.let { binding ->
    (binding as? ListItemMapBinding)?.let {
    holder.moveCamera(mapListItem.campusAddress)
    }

    View full-size slide

  14. うまくいったこと
    RecyclerViewのサイクルに合わせた表示処理
    - onViewRecycledでclear
    recyclerView.setRecyclerListener { holder ->
    if (holder is MapViewHolder) { holder.releaseMap() }
    }
    fun releaseMap() {
    googleMap?.run {
    clear()
    mapType = GoogleMap.MAP_TYPE_NONE
    }
    }

    View full-size slide

  15. つまずいたこと
    Missteps

    View full-size slide

  16. 最初の一個以外真っ白になった
    MAP
    つまずいたこと

    View full-size slide

  17. つまずいたこと
    FragmentRecyclerViewと相性が悪いらしく、
    結局MapViewにした…
    (公式サンプルでもViewだった…)
    参考:
    https://stackoverflow.com/questions/50391459/supportmapfra
    gment-on-a-recyclerview

    View full-size slide

  18. 途中のアイテムが世界地図のままのことがある
    (視点位置が指定した場所に移動していない)
    つまずいたこと
    これ
    MAP
    MAP
    MAP

    View full-size slide

  19. つまずいたこと
    RecyclerView内の表示準備不備が原因
    - 表示にはMapクラスとAddressクラスが必要
    - onCreateViewHolderでgetMapAsync
    - onBindViewHolderでitemの持つAddressにMapの
    カメラ位置を移動させたいが、まだ取得できてない
    onCreate
    ViewHolder
    onBind
    ViewHolder
    (Address取得)
    視点移動
    したいのに
    Mapがない!
    Map取得!
    時間(t)
    getMapAsync

    View full-size slide

  20. MapとAddress両方をHolderでメンバ保持し、
    どちらかが取れたタイミングで
    視点移動処理を試す
    つまづいたこと
    onCreate
    ViewHolder
    onBind
    ViewHolder
    (Address取得)
    getMap
    Async
    ItemのAddress
    取得!可能なら
    視点移動!
    Map取得!
    可能なら
    視点移動!
    時間(t)

    View full-size slide

  21. override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) =
    ~~
    holder.binding.campusMap.getMapAsync { map ->
    MapsInitializer.initialize(holder.itemView.context.applicationContext)
    holder.showMapIfAble(map)
    mapType = GoogleMap.MAP_TYPE_NORMAL
    }
    }
    }
    つまづいたこと

    View full-size slide

  22. まとめ
    Result

    View full-size slide

  23. - 公式サンプルはきちんと見よう
    - ViewのLifeCycleを気にしよう

    View full-size slide

  24. https://info.studyplus.co.jp/recruit

    View full-size slide

  25. ご静聴ありがとうございました

    View full-size slide