导航项更改不会更新回收者视图

时间:2020-09-11 15:52:42

标签: android kotlin android-recyclerview

我有一个带有导航视图的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未附加到上下文。

2 个答案:

答案 0 :(得分:1)

为什么: 没错,EventDayFragment视图没有被破坏,因此onViewCreated在数据第一次工作时仅被调用一次,并且创建了EventSchedule的子片段(据我所知EventSchedule包含viewPager和两个子片段Day 1日程和Day 2日程),但是当您单击关于我们时,EventsSchedule片段本身不会被销毁,但这不一定适用于其子级(第1天计划和第2天计划),并且在重新创建子项时,它们可能会被破坏。第二次,他们找不到数据(因为父母没有像他们一样被破坏)

如何解决: 我认为有很多解决方案:

  1. 在子片段的onViewCreated()内向父片段询问数据,并在子片段自身内部制作loadDataToRecyclerView(day)。

  2. (快速但不建议使用)尝试将loadDataToRecyclerView(day)移至 onResume()而不是onViewCreated()

答案 1 :(得分:1)

问题在于,每次我创建父片段的视图时都不会调用子片段的onViewCreated(view: View, savedInstanceState: Bundle?)。这是因为这一行代码:

binding.viewPagerScheduleDay.adapter = EventDayPagerAdapter(requireActivity().supportFragmentManager)

传递活动的FragmentManager并没有告诉应用程序每次都创建子片段的视图。

相反,我们必须添加以下代码:

binding.viewPagerScheduleDay.adapter = EventDayPagerAdapter(childFragmentManager)

这很好用!