如何解决无法在底部导航中维护数据
关于显示来自 API 的数据,我有一个非常令人困惑的问题。这个问题涉及我使用底部导航和选项卡布局。为了在此处提供上下文,我想展示我的 android 应用程序的结构。下面是我的 HomeActivity.kt
外观的图片:
如您所见,我在底部导航中有 4 个选项。这里的问题是我有一个选项,即新闻选项。大致是这样的:
在新闻选项卡中,我正在从 API 获取数据。为了在此处提供更多上下文,我更改选项的方式是替换活动中的片段。这是我放入 HomeActivity.kt
作为全局变量的片段中的代码:
private val sosFragment = SosFragment()
private val newsFragment = NewsFragment()
private val helpFragment = TipsFragment()
private val settingsFragment = SettingsFragment()
使用 onCreate()
的 HomeActivity.kt
:
binding.bottomNavigation.setOnNavigationItemSelectedListener {
when(it.itemId){
R.id.ic_sos -> replaceFragment(sosFragment)
R.id.ic_news -> replaceFragment(newsFragment)
R.id.ic_tips -> replaceFragment(helpFragment)
R.id.ic_settings -> replaceFragment(settingsFragment)
}
true
}
此处使用 replaceFragment(fragment: Fragment)
函数:
private fun replaceFragment(fragment: Fragment){
if (fragment!=null){
val transaction = supportFragmentManager.beginTransaction()
transaction.replace(R.id.fragment_container,fragment)
transaction.commit()
}
}
新闻片段在我第一次导航到新闻选项卡时完美运行,并且新闻很好地显示在回收站视图中,但问题在于 -> 当我导航到另一个片段时,让我们说 HelpFragment()
并导航再次回到 NewsFragment()
片段突然空了。为了提供更多上下文,我在 NewsFragment()
中使用了选项卡布局。所以在我的 NewsFragment()
中,它包含健康、科学和娱乐的其他三个片段。 NewsFragment()
代码如下所示:
class NewsFragment : Fragment() {
private lateinit var binding: FragmentNewsBinding
override fun onCreateView(inflater: LayoutInflater,container: ViewGroup?,savedInstanceState: Bundle?): View? {
// Inflate the layout for this fragment
binding = FragmentNewsBinding.inflate(inflater,container,false)
return binding.root
}
override fun onViewCreated(view: View,savedInstanceState: Bundle?) {
super.onViewCreated(view,savedInstanceState)
setUpTabs()
}
private fun setUpTabs(){
val sectionsPagerAdapter = activity?.let {
SectionsPagerAdapter(requireContext(),it.supportFragmentManager)
}
binding.viewPager.adapter = sectionsPagerAdapter
binding.tabs.setupWithViewPager(binding.viewPager)
}
}
使用具有此代码的 SectionsPagerAdapter.kt
:
class SectionsPagerAdapter(private val mContext: Context,fm: FragmentManager): FragmentPagerAdapter(fm,BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT) {
companion object {
@StringRes
private val TAB_TITLES = intArrayOf(R.string.health,R.string.science,R.string.entertainment)
}
override fun getCount(): Int {
return TAB_TITLES.size
}
override fun getItem(position: Int): Fragment {
return when(position){
0 -> HealthFragment()
1 -> ScienceFragment()
2 -> EntertainmentFragment()
else -> Fragment()
}
}
override fun getPageTitle(position: Int): CharSequence? {
return mContext.resources.getString(TAB_TITLES[position])
}
}
这是我的 HealthFragment.kt
示例,与使用自己的 ViewModel 的 Science 和 Entertainment 片段大致相同。
class HealthFragment : Fragment() {
private lateinit var binding: FragmentNewsListBinding
companion object{
private const val CATEGORY = "health"
}
override fun onCreateView(
inflater: LayoutInflater,savedInstanceState: Bundle?
): View? {
binding = FragmentNewsListBinding.inflate(inflater,savedInstanceState)
val rvNews = binding.rvNews
rvNews.layoutManager = LinearLayoutManager(context)
val listNewsAdapter = ListNewsAdapter()
val viewModel = HealthNewsViewModel(NewsRepository.getInstance(NewsDataSource()))
val status = viewModel.getStatus()
if (!status){
binding.tvFail.visibility = View.VISIBLE
} else {
binding.tvFail.visibility = View.GONE
}
viewModel.getHealthNews().observe(requireActivity(),{articles->
listNewsAdapter.setData(articles)
listNewsAdapter.setCategory(CATEGORY)
rvNews.adapter = listNewsAdapter
})
viewModel.isLoading().observe(requireActivity(),{isLoading->
if (isLoading){
binding.progressBar.visibility = View.VISIBLE
} else {
binding.progressBar.visibility = View.GONE
}
})
}
}
来自我的研究和调试过程。我认为这个问题的问题是我对片段生命周期的理解,所以我尝试将所有 ViewModel 代码放在 onStart()
方法上,因为它仍然不起作用。我也尝试将它放在 onResume()
或 onCreateView()
上,但似乎没有任何效果。这就像 recyclerview 只会在第一次创建片段和我第一次打开应用程序时显示。一旦我再次尝试打开它,它就不会出现。
导致此问题的可能原因是什么?
更新:
调试后,我发现问题是当我调用 NewsFragment()
时,标签布局中包含在 NewsFragment()
中的片段没有被调用来创建({{1} onCreate()
的 } 没有被调用!)。我发现这是问题的原因,但我不确定为什么会发生..
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。