findFragmentByTag продолжает возвращать значение Null в Android с помощью ViewPager

#android #kotlin #android-viewpager2 #fragmentstateadapter

Вопрос:

Я пытался передать данные из родительской активности в viewPager , и я нашел решение, используя findFragmentByTag , но оно возвращает значение Null, и я не уверен, что я пропустил.

В примере, который я нашел, использовался устаревший FragmentPagerAdapter , и я думаю, что, возможно, именно поэтому моя реализация не работает, поэтому я ищу путь вперед.

 (supportFragmentManager.findFragmentByTag(tag) as StopwatchFragment?)?.displayData(
            min!!,
            sec!!,
            millis!!
        )
 

равно нулю

Основная Деятельность

 class MainActivity : AppCompatActivity(), StopwatchListener {
override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivityMainBinding.inflate(layoutInflater)
       ...
        binding.viewPagerMain.adapter = PageAdapter(supportFragmentManager, lifecycle)
       
    }
...
 override fun getTheTime(min: String?, sec: String?, millis: String?) {
        val tag =
            "android:switcher:"   R.id.view_pager_main.toString()   ":"   binding.viewPagerMain.currentItem
        Log.d("Main", tag)
        (supportFragmentManager.findFragmentByTag(tag) as StopwatchFragment?)?.displayData(
            min!!,
            sec!!,
            millis!!
        )
    }
}
 

Адаптер страницы

 class PageAdapter(fragmentManager: FragmentManager, lifecycle: Lifecycle) :
    FragmentStateAdapter(fragmentManager, lifecycle) {

    override fun getItemCount() = 3

    override fun createFragment(position: Int): Fragment {
        return when (position) {
            0 -> {
                RepsFragment()
            }
            1 -> {
                StopwatchFragment()
            }
            2 -> {
                TimerFragment()
            }
            else -> {
                RepsFragment()
            }
        }
    }
}
 

Ответ №1:

 val tag =
        "android:switcher:"   R.id.view_pager_main.toString()   ":"   binding.viewPagerMain.currentItem
 

Это справедливо для ViewPager «нет ViewPager2 «.

Для того , чтобы это сделать ViewPager2 , вам нужно:

 val tag = "f$pageId"
 

И для этого требуется иметь уникальные идентификаторы для страниц, для простоты вы можете установить их в качестве ViewPager позиций; для этого переопределите getItemId() адаптер:

 class PageAdapter(fragmentManager: FragmentManager, lifecycle: Lifecycle) :
    FragmentStateAdapter(fragmentManager, lifecycle) {

    // ... 

    override fun getItemId(position: Int): Long {
        return position.toLong()
    }
}
 

И тогда pageId будет текущая страница (или любая позиция страницы, которую вы хотите), и, следовательно, тег будет:

 val tag = "f$binding.viewPagerMain.currentItem"
 

Комментарии:

1. Ошибка изменилась, теперь она говорит конкретно null cannot be cast to non-null type com.homeofficeprojects.countmyrepstoo.StopwatchFragment . Таким supportFragmentManager образом, он все еще не находит фрагмент

2. Это поднято на (supportFragmentManager.findFragmentByTag(tag) as StopwatchFragment?) ?

3. нет, код, который я использовал, удаляет проверки на пустоту, потому что данные не передавались, и я хотел посмотреть, где произошло отключение val tag = «f${привязка.viewPagerMain.CurrentItem}» val f = supportFragmentManager.findFragmentByTag(тег) в качестве фрагмента секундомера }

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

5. похоже, что независимо от того, где я размещаю вызов функции, она, похоже, не находит фрагмент