Я получаю исключение:
E/MessageQueue-JNI: java.lang.IllegalArgumentException: No view found for id 0x7f0a0554 (ua.com.company.app:id/vpBanners) for fragment BannerItemFragment{30698be} (4c80b228-4303-4c80-b99d-a55b8359b8c2) id=0x7f0a0554}
Моя иерархия выглядит так:
Иерархия экранов
Мой адаптер для vpHome
:
class HomeViewPagerAdapter(fm: FragmentManager) : FragmentStatePagerAdapter(fm, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT) {
private val mFragmentList: MutableList<Fragment> = ArrayList()
private val mFragmentTitleList: MutableList<String> = ArrayList()
override fun getItem(position: Int): Fragment {
return mFragmentList[position]
}
override fun getCount(): Int {
return mFragmentList.size
}
override fun getPageTitle(position: Int): CharSequence? {
return mFragmentTitleList[position]
}
fun addFragment(fragment: Fragment, title: String) {
mFragmentList.add(fragment)
mFragmentTitleList.add(title)
}
}
А я применяю его таким образом:
private fun setupViewPager(viewPager: DisableSwipeViewPager) {
vpAdapter = HomeViewPagerAdapter(childFragmentManager).apply {
addFragment(ForYouFragment(), "for you")
addFragment(AnotherFragment1(), "a1")
addFragment(AnotherFragment2(), "a2")
}
viewPager.adapter = vpAdapter
}
Далее мой SnapBannersCarouselViewHolder
для обработки элементы с ViewPager
внутри:
class SnapBannersCarouselViewHolder(
private val mBinding: HomeFragmentItemSnapBannersCarouselBinding
) : RecyclerView.ViewHolder(mBinding.root) {
companion object {
// ...
fun newInstance(
inflater: LayoutInflater,
parent: ViewGroup,
onMoreInteractionListener: ((infoBlockId: String) -> Unit)?
): SnapBannersCarouselViewHolder {
val binding =
HomeFragmentItemSnapBannersCarouselBinding.inflate(inflater, parent, false)
return SnapBannersCarouselViewHolder(
binding,
onMoreInteractionListener
)
}
}
fun bind(item: SnapBannersItem, fragmentManager: FragmentManager) {
// ...
val adapter = BannerPagesAdapter(fragmentManager, item.banners)
with(mBinding.vpBanners) {
// ...
this.adapter = adapter
offscreenPageLimit = 3
}
}
}
Мой адаптер RecyclerView ForYouContentAdapter
:
class ForYouContentAdapter(
var data: List<HomeBaseItem> = emptyList(),
var fragmentManagerRetriever: () -> FragmentManager
) : BaseRecyclerViewAdapter<HomeBaseItem>(data) {
enum class ViewType(val value: Int) {
// ...
SNAP_BANNERS(6)
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
return when (viewType) {
// ...
ViewType.SNAP_BANNERS.value -> SnapBannersCarouselViewHolder.newInstance(
mInflater!!,
parent,
onBannersMoreInteractionListener // todo possibly change it
)
else -> throw RuntimeException("Can not create view holder for undefined view type")
}
}
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
when (getItemViewType(position)) {
// ...
ViewType.SNAP_BANNERS.value -> {
val vHolder = holder as SnapBannersCarouselViewHolder
vHolder.bind(
getItem(position) as SnapBannersItem,
fragmentManagerRetriever.invoke()
)
}
}
}
}
И моя реализация fragmentManagerRetriever
в ForYouFragment
выглядит так:
private val fragmentManagerRetriever: () -> FragmentManager = {
childFragmentManager
}
Мой BannerItemFragment
код:
class BannerItemFragment : Fragment() {
private lateinit var mBinding: HomeFragmentSnapBannerItemBinding
companion object {
// ...
fun newInstance(
item: RectWebViewItem
): BannerItemFragment {
return BannerItemFragment()
}
}
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
mBinding = HomeFragmentSnapBannerItemBinding.inflate(inflater, container, false)
return mBinding.root
}
// ...
}
В каждом месте, где мне нужно создавать фрагменты внутри других фрагментов, я использую childFragmentManager
.
И когда я открываю ForYouFragment
первый раз, нормально работает. Мой товар с ViewPager
работает нормально. Но когда я заменяю фрагмент в контейнере Activity (добавляя в задний стек), находящийся на ForYouFragment
, а затем возвращаюсь обратно (обратно на HomeFragment
, потому что ForYouFragment
внутри HomeFragment
), я получаю ошибку.
Для замены фрагментов я использую этот метод внутри ForYouFragment
:
private fun showAnotherFragment() {
ActivityUtils.replaceFragmentToActivity(
requireActivity(),
SomeFragment.newInstance(),
true
)
}
и ActivityUtils
код:
object ActivityUtils {
fun replaceFragmentToActivity(
activity: FragmentActivity,
fragment: Fragment,
addToBackStack: Boolean
) {
replaceFragmentToActivity(activity, fragment, addToBackStack, containerId = R.id.fragmentContainer)
}
fun replaceFragmentToActivity(
activity: FragmentActivity,
fragment: Fragment,
addToBackStack: Boolean,
containerId: Int
) {
val fragmentManager = activity.supportFragmentManager
val transaction = fragmentManager.beginTransaction()
transaction.replace(containerId, fragment)
if (addToBackStack) {
transaction.addToBackStack(null)
}
transaction.commitAllowingStateLoss()
}
}
Пожалуйста, помогите мне понять, почему я получаю это исключение?
UPD
Адаптер для ViewPager
внутри RecyclerView:
class BannerPagesAdapter(
fragmentManager: FragmentManager,
var data: List<RectWebViewItem>
) : FragmentStatePagerAdapter(
fragmentManager,
BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT
) {
private var fragments: MutableList<BannerItemFragment> = mutableListOf()
init {
// initial empty fragments
for (i in data.indices) {
fragments.add(BannerItemFragment())
}
}
override fun getItem(position: Int): Fragment {
return BannerItemFragment.newInstance(data[position])
}
override fun getCount(): Int {
return fragments.size
}
override fun instantiateItem(container: ViewGroup, position: Int): Any {
val f = super.instantiateItem(container, position)
fragments[position] = f as BannerItemFragment
return f
}
}