我有一个带有导航视图的DrawerLayout活动。这些项目是“主页”,“关于我们”,“事件时间表”等。事件时间表有一个片段,其中包含一个底部导航抽屉和一个视图寻呼机。 viewpager仅附带2个片段-第1天时间表和第2天时间表。同样,底部导航中只有2个项目。每个片段都有一个回收站视图,在其中显示事件列表及其日期和时间。
启动应用程序时,主页片段会按预期方式弹出。我转到导航抽屉,然后单击“事件时间表”。回收者视图将加载数据。我可以在查看寻呼机上滑动。一切正常。
但是现在当我单击“关于我们”时,该片段照常打开。当我重新打开“事件和计划”时,“回收者”视图不显示任何列表项。第一次单击该按钮有效,但第二次,第三次单击不起作用。
EventsFragment.kt(带有viewpager和底部导航的主要片段):
class EventsFragment : Fragment(R.layout.fragment_events) {
...
private fun setupViewPager() {
binding.viewPagerScheduleDay.adapter = EventDayPagerAdapter(requireActivity().supportFragmentManager)
binding.bottomNav.setOnNavigationItemSelectedListener {
when (it.itemId) {
R.id.mDay1 -> binding.viewPagerScheduleDay.currentItem = 0
R.id.mDay2 -> binding.viewPagerScheduleDay.currentItem = 1
}
true
}
}
}
EventDayFragment.kt(viewpager中的片段):
class EventDayFragment : Fragment(R.layout.fragment_event_day) {
...
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
binding = FragmentEventDayBinding.bind(view)
val day = arguments?.getInt(PARAM_1)!!
loadDataToRecyclerView(day)
}
private fun loadDataToRecyclerView(day: Int) {
Database.getEventsFromDay(day) { events ->
events?.let {
val eventAdapter = EventScheduleRecyclerAdapter(requireContext(), it)
binding.recyclerViewEventsSchedule.apply {
layoutManager = StaggeredGridLayoutManager(2, VERTICAL)
adapter = eventAdapter
setHasFixedSize(true)
}
} ?: requireContext().toast("Error Encountered in collecting data.")
}
}
}
在我的代码中,我注意到在EventDayFragment.kt中,onViewCreated函数仅被调用一次。这就是为什么recyclerview只工作一次的原因。我该如何解决?
修改
class EventDayFragment : Fragment(R.layout.fragment_event_day) {
companion object {
...
var isAlive = false
}
override fun onAttach(context: Context) {
super.onAttach(context)
isAlive = true
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
binding = FragmentEventDayBinding.bind(view)
val day = arguments?.getInt(PARAM_1)!!
loadDataToRecyclerView(day)
}
private fun loadDataToRecyclerView(day: Int) {
... // Same as before
}
override fun onPause() {
super.onPause()
isAlive = false
}
}
我添加了一个静态布尔变量,以了解该片段是否正在运行。在EventsFragment中,我将此代码添加到了setupViewPager()
:
private fun setupViewPager() {
val eventDayFragmentAdapter = EventDayFragmentAdapter(
requireActivity().supportFragmentManager
)
binding.viewPagerScheduleDay.adapter = eventDayFragmentAdapter
val fragment = eventDayFragmentAdapter.getItem(binding.viewPagerScheduleDay.currentItem)
if (EventDayFragment.isAlive)
fragment.loadDataToRecyclerView(binding.viewPagerScheduleDay.currentItem + 1)
binding.bottomNav.setOnNavigationItemSelectedListener {
when (it.itemId) {
R.id.mDay1 -> binding.viewPagerScheduleDay.currentItem = 0
R.id.mDay2 -> binding.viewPagerScheduleDay.currentItem = 1
}
true
}
}
执行此编辑后,出现此错误:EventDayFragment未附加到上下文。
答案 0 :(得分:1)
为什么: 没错,EventDayFragment视图没有被破坏,因此onViewCreated在数据第一次工作时仅被调用一次,并且创建了EventSchedule的子片段(据我所知EventSchedule包含viewPager和两个子片段Day 1日程和Day 2日程),但是当您单击关于我们时,EventsSchedule片段本身不会被销毁,但这不一定适用于其子级(第1天计划和第2天计划),并且在重新创建子项时,它们可能会被破坏。第二次,他们找不到数据(因为父母没有像他们一样被破坏)
如何解决: 我认为有很多解决方案:
在子片段的onViewCreated()内向父片段询问数据,并在子片段自身内部制作loadDataToRecyclerView(day)。
(快速但不建议使用)尝试将loadDataToRecyclerView(day)移至 onResume()而不是onViewCreated()
答案 1 :(得分:1)
问题在于,每次我创建父片段的视图时都不会调用子片段的onViewCreated(view: View, savedInstanceState: Bundle?)
。这是因为这一行代码:
binding.viewPagerScheduleDay.adapter = EventDayPagerAdapter(requireActivity().supportFragmentManager)
传递活动的FragmentManager并没有告诉应用程序每次都创建子片段的视图。
相反,我们必须添加以下代码:
binding.viewPagerScheduleDay.adapter = EventDayPagerAdapter(childFragmentManager)
这很好用!