android MapView + ViewPager2 + проблема с привязкой данных

Недавно я столкнулся с очень странной проблемой. В моем макете было представление карты, которое было увеличено с помощью привязки данных. После того, как я добавил ViewPager2 в свой макет, у меня возникла эта проблема:

java.lang.IllegalArgumentException: Wrong state class, expecting View State but received class androidx.recyclerview.widget.RecyclerView$SavedState instead. This usually happens when two views of different type have the same id in the same hierarchy. This view's id is id/0x1. Make sure other views do not use the same id.

Но это происходит только тогда, когда вы сначала открываете первый фрагмент и переходите к следующему, а затем нажимаете назад.

  • Если я уберу карту из своего макета, все будет работать.
  • Если я уберу viewpager2 из своего макета, все будет работать.
  • Если я удаляю привязку данных, все работает.

Кажется, это как-то связано с состоянием просмотра, но могу ли я что-нибудь сделать, чтобы решить эту проблему?

Вот пример кода фрагмента:

class TestFragment(override val layoutRes: Int = R.layout.fragment_test) : BaseFragment() {

lateinit var binding: FragmentTestBinding

override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
    binding = FragmentTestBinding.inflate(inflater, container, false)
    setupMap(savedInstanceState)
    return binding.root
}

override fun onResume() {
    super.onResume()
    binding.mapView.onResume()
}

override fun onPause() {
    super.onPause()
    binding.mapView.onPause()
}

private fun setupMap(savedInstanceState: Bundle?) {
    binding.mapView.onCreate(savedInstanceState)
    binding.mapView.onResume()
    binding.mapView.getMapAsync { }
}
}

Пример макета:

<?xml version="1.0" encoding="utf-8"?>
<layout>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="match_parent"
    android:layout_height="match_parent">

    <com.google.android.gms.maps.MapView
        android:id="@+id/mapView"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

    <androidx.viewpager2.widget.ViewPager2
        android:id="@+id/viewPager"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

</FrameLayout>
</layout>

Чтобы воспроизвести, мне нужно открыть другой фрагмент, а затем нажать назад

** РЕДАКТИРОВАТЬ: ** Похоже, что перемещение окна просмотра перед картой также помогает, поэтому привязку данных все еще можно использовать.


person SMGhost    schedule 14.08.2019    source источник
comment
Привет, ты нашел причину проблемы? Эта проблема сводит меня с ума :С   -  person lelloman    schedule 30.01.2020
comment
@lelloman, я думаю, что в итоге я использовал старый просмотрщик. Рад видеть, что вы нашли другое решение :)   -  person SMGhost    schedule 01.02.2020
comment
У вас точно такая же проблема, может вы нашли решение? В настоящее время единственное решение, которое я вижу, - это использовать ViewPager вместо ViewPager2...   -  person RadoVidjen    schedule 05.04.2020
comment
Странно, когда я размещаю viewPager2 за картой, он работает, однако его нельзя увидеть, так как mapView покрывает VP2...   -  person RadoVidjen    schedule 05.04.2020


Ответы (1)


Проблема, похоже, в том, что MapView и ViewPager2 завышают представления и присваивают им динамически генерируемые идентификаторы.

ViewPager2 (версия 1.0.0 atm) делает это, вызывая ViewCompat.generateViewId(), я понятия не имею, что делает MapView, он не использует LayoutInflater для расширения своих дочерних представлений, и я подозреваю, что он также не вызывает ViewCompat.generateViewId().

Причина проблемы в том, что иерархия представлений в конечном итоге содержит 2 View с одним и тем же идентификатором (со значением 1 для меня), один - RecyclerView внутри ViewPager2 (TIL, что ViewPager2 является оболочкой RecyclerView, удивительно), другой представляет собой LinearLayout, содержащий 2 ImageView внутри MapView.

В настоящее время я взламываю эту неприятную ситуацию, вызывая:

for(i in 0 until 1000) ViewCompat.generateViewId()

до setContentView(Int) в Activity.

person lelloman    schedule 30.01.2020