业余 Android:PagerView + Fragment 一些问题 时间: 2021-01-05 18:45 分类: JAVA ####前言 `github`上找了一个开源的顶部横向滚动导航:https://github.com/ogaclejapan/SmartTabLayout 我预期想要的效果就是刚进入app的时候加载第一个导航内容,随后用户切换导航再切换回去的时候能够看到原先的内容,也就是加载过的导航`Fragment`不进行销毁。 ####问题 结果发现,打开app会预先加载两个导航`Fragment`,然后切换导航的时候,如果两个导航之间的距离大于1,那么之前的导航`Fragment`将被销毁,也就是说`PagerView`只缓存两个`Fragment`。 一开始想,算了,那就搞成切换即销毁当前`Fragment`吧,这样一来切换导航都会有个加载内容的动画效果,而不是缓存两个`Fragment`时,有时有加载动画有时没有,用户还会以为是`BUG`。 但是,由于是业余`Android`,完全无法下手,还以为是那个导航开源库的问题。 后来才发现是`PagerView`的懒加载机制导致的。 最好的预期效果就是`PagerView`能够保存所有`Fragment`的状态,又能够是在切换导航时没有加载过的才进行加载。 但是最终发现,无法改成每次切换都重新加载,因为默认总是会至少懒加载一个`Fragment`,所以我选择一次性把所有的`Fragment`都预加载了,后面切换导航`Fragment`不会销毁重建。 设置参数就是:`offscreenPageLimit`,有多少个导航就设置几,这样一来就在启动的时候会一次性把所有的导航内容都加载。 ####补充 最后完美解决方案:预加载所有`Fragment`但不加载数据,只有切换过去第一次才加载。 `offscreenPageLimit`还是按上面说的多少个导航条目就设置多少(当然了,注意内存消耗,根据自身情况要不要这样做) 然后就是重写`Fragment`的`setUserVisibleHint`方法,整个例子如下: ``` class SubFragment: Fragment() { private var _hasLoadedOnce = false override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View? { val root = inflater.inflate(R.layout.fragment_movie_sub, container, false) val position = FragmentPagerItem.getPosition(arguments) //仅第一项导航内容在创建时加载,其他导航切换时再在 setUserVisibleHint 中加载数据 if (position == 0) { loadData() } root.findViewById(R.id.test).text = Random.nextInt().toString() return root } override fun setUserVisibleHint(isFragmentVisible_: Boolean) { super.setUserVisibleHint(true) if (this.isVisible) { // we check that the fragment is becoming visible if (isFragmentVisible_ && !_hasLoadedOnce) { _hasLoadedOnce = true loadData() } } } private fun loadData() { } } ``` 标签: 无