0

I'm using MapView inside my custom Fragment and I forwarded all life cycle methods to MapView. I have an issue with infinite surface update on tablet (even on tablet emulator: HAXM Nexus 10 API30) but not on any phone. I removed all functions, except necessary for MapView implementation but issue is still present.

This infinite surface update causing issue to RecyclerView adapter because onBindViewHolder is triggered multiple times (~20) by sec.

I want to know how to stop this unexpected behaviour of MapView or atleast limit number of events send to RecyclerView.Adapter.

MapViewFragment:

class MapIssueFragment: Fragment(R.layout.fragment_map), OnMapReadyCallback {
    companion object {
        private const val TAG = "MapIssueFragment"

        fun newInstance(): MapIssueFragment{
            return MapIssueFragment()
        }
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        Log.i(TAG, "onCreate")
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

        Log.i(TAG, "onViewCreated")

        map.apply {
            onCreate(savedInstanceState)
            getMapAsync(this@MapIssueFragment)
        }
    }

    override fun onStart() {
        super.onStart()
        map.onStart()

        Log.i(TAG, "onStart")
    }

    override fun onResume() {
        super.onResume()
        map.onResume()

        Log.i(TAG, "onResume")
    }

    override fun onPause() {
        super.onPause()
        map.onPause()

        Log.i(TAG, "onPause")
    }

    override fun onStop() {
        super.onStop()
        map.onStop()

        Log.i(TAG, "onStop")
    }

    override fun onDestroy() {
        super.onDestroy()
        map.onDestroy()

        Log.i(TAG, "onDestroy")
    }

    override fun onSaveInstanceState(outState: Bundle) {
        super.onSaveInstanceState(outState)
        map.onSaveInstanceState(outState)

        Log.i(TAG, "onSaveInstanceState")
    }

    override fun onLowMemory() {
        super.onLowMemory()
        map.onLowMemory()

        Log.i(TAG, "onLowMemory")
    }

    private lateinit var googleMap: GoogleMap

    override fun onMapReady(googleMap: GoogleMap) {
        this.googleMap = googleMap
    }
}

fragment_map:

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <com.google.android.gms.maps.MapView
        android:id="@+id/map"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintBottom_toTopOf="@id/requirements_container"/>

    <androidx.constraintlayout.widget.ConstraintLayout
        android:id="@+id/requirements_container"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintHeight_percent="0.50"
        android:visibility="visible"
        >

        <TextView
            android:id="@+id/requirements_empty"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:text="@string/no_requirements"
            android:gravity="center"
            android:visibility="gone"
            />

        <androidx.recyclerview.widget.RecyclerView
            android:id="@+id/requirements_list"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            tools:listitem="@layout/item_requirement_detail"
            />

    </androidx.constraintlayout.widget.ConstraintLayout>

</androidx.constraintlayout.widget.ConstraintLayout>

Even without RecyclerView adapter I can see error in Logcat where you can see that refresh rate:

2020-10-27 13:47:50.908 E/RecyclerView: No adapter attached; skipping layout
2020-10-27 13:47:50.914 E/RecyclerView: No adapter attached; skipping layout
2020-10-27 13:47:50.963 E/RecyclerView: No adapter attached; skipping layout
2020-10-27 13:47:50.972 E/RecyclerView: No adapter attached; skipping layout
2020-10-27 13:47:51.025 E/RecyclerView: No adapter attached; skipping layout
2020-10-27 13:47:51.029 E/RecyclerView: No adapter attached; skipping layout
2020-10-27 13:47:51.075 E/RecyclerView: No adapter attached; skipping layout
2020-10-27 13:47:51.092 E/RecyclerView: No adapter attached; skipping layout
Tomas Ivan
  • 2,212
  • 2
  • 21
  • 34
  • What do you mean by infinite surface update? How is related to `RecyclerView`? – Xid Oct 27 '20 at 20:34
  • I'm not sure how its related but look like surface update trigger adapter update - as you can see from logcat. Frequency of surface update was identified by `developer option - show surface updates` and in profiler I can see ~50% cpu usage in idle when `MapIssueFragment` is shown (0-3% on other screens). – Tomas Ivan Oct 28 '20 at 07:05
  • All of this is tablet issue only. Phone works with this implementation without any issue - surface update is normal (if nothing changed then surface update is not made) and CPU usage is 0-3% when idle. – Tomas Ivan Oct 28 '20 at 07:14

1 Answers1

0

I found workaround thanks to this question. Set MapView.layerType to hardware reduced refresh rate. It's just workaround and not proper solution!

<com.google.android.gms.maps.MapView
        android:id="@+id/map"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layerType="hardware"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintBottom_toTopOf="@id/map_change_size_button"/>
Tomas Ivan
  • 2,212
  • 2
  • 21
  • 34