Android开发问题——ViewPager嵌套时Fragment的UserVisibleHint属性不同步
具体问题如下:
现有如下结构:
MainActivity(ViewPager)
Fragment1
Fragment2(ViewPager)
Fragment2-1
Fragment2-2
Fragment3
Fragment4
当我们进入MainActivity的时候,MainActivity的viewpager会进行初始化,初始化完毕之后的状态是
MainActivity(ViewPager)
Fragment1.UserVisibleHint=true
Fragment2(ViewPager).UserVisibleHint=false
Fragment2-1.UserVisibleHint=true
Fragment2-2.UserVisibleHint=false
Fragment3.UserVisibleHint=false
Fragment4.UserVisibleHint=false
可以发现Fragment2的UserVisibleHint为false,而他的第一个子fragment2-1的UserVisibleHint为true
而我们实现懒加载时,需要以UserVisibleHint这个属性来判断是否加载数据,因此当我们进入MainActivity的时候,Fragment1会加载数据,Fragment2-1同样也会加载数据,如何避免Fragment2-1不加载数据呢?因为此时我们只想加载Fragment1的数据。Fragment2-1的UserVisibleHint在我们视觉的真正意义上是false。ViewPager并未提供解决此问题的方法,得靠自己来解决。
先来解决初始化时候让Fragment2-1.UserVisibleHint为false
解决思路就是在子Fragment onAttach的时候检查其父Fragment的mUserVisibleHint属性的状态,如果是false就强制将当前子Fragment的mUserVisibleHint属性设置为false并设置一个恢复标记(因为接下来还需要恢复) 然后在父Fragment setUserVisibleHint为true的时候检查其所有子Fragment,有恢复标记的子Fragment,设置其mUserVisibleHint属性为true,看代码:
public class BaseFragment extends Fragment{ private boolean waitingShowToUser; public void onActivityCreated([@Nullable](https://my.oschina.net/u/2896689) Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); // 如果自己是显示状态,但父Fragment却是隐藏状态,就把自己也改为隐藏状态,并且设置一个等待显示标记 if(getUserVisibleHint()){ Fragment parentFragment = getParentFragment(); if(parentFragment != null && !parentFragment.getUserVisibleHint()){ waitingShowToUser = true; super.setUserVisibleHint(false); } } } [@Override](https://my.oschina.net/u/1162528) public void setUserVisibleHint(boolean isVisibleToUser) { super.setUserVisibleHint(isVisibleToUser); if(getActivity() != null) { List<Fragment> childFragmentList = getChildFragmentManager().getFragments(); if (isVisibleToUser) { // 将所有正等待显示的子Fragment设置为显示状态,并取消等待显示标记 if (childFragmentList != null && childFragmentList.size() > 0) { for (Fragment childFragment : childFragmentList) { if (childFragment instanceof BaseFragment) { BaseFragment childBaseFragment = (BaseFragment) childFragment; if (childBaseFragment.isWaitingShowToUser()) { childBaseFragment.setWaitingShowToUser(false); childFragment.setUserVisibleHint(true); } } } } } } } public boolean isWaitingShowToUser() { return waitingShowToUser; } public void setWaitingShowToUser(boolean waitingShowToUser) { this.waitingShowToUser = waitingShowToUser; } }
接下来解决父ViewPager切换的时候同步其子Fragment的UserVisibleHint属性
思路就是在父Fragment setUserVisibleHint为false的时候将其所有mUserVisibleHint为true的子Fragment都强制改为false,然后设置一个恢复标记,然后在setUserVisibleHint为true的时候再恢复,看代码:
public class BaseFragment extends Fragment{ private boolean waitingShowToUser; public void onActivityCreated([@Nullable](https://my.oschina.net/u/2896689) Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); // 如果自己是显示状态,但父Fragment却是隐藏状态,就把自己也改为隐藏状态,并且设置一个等待显示标记 if(getUserVisibleHint()){ Fragment parentFragment = getParentFragment(); if(parentFragment != null && !parentFragment.getUserVisibleHint()){ waitingShowToUser = true; super.setUserVisibleHint(false); } } } @Override public void setUserVisibleHint(boolean isVisibleToUser) { super.setUserVisibleHint(isVisibleToUser); // 父Fragment还没显示,你着什么急 if (isVisibleToUser) { Fragment parentFragment = getParentFragment(); if (parentFragment != null && !parentFragment.getUserVisibleHint()) { waitingShowToUser = true; super.setUserVisibleHint(false); return; } } if(getActivity() != null) { List<Fragment> childFragmentList = getChildFragmentManager().getFragments(); if (isVisibleToUser) { // 将所有正等待显示的子Fragment设置为显示状态,并取消等待显示标记 if (childFragmentList != null && childFragmentList.size() > 0) { for (Fragment childFragment : childFragmentList) { if (childFragment instanceof BaseFragment) { BaseFragment childBaseFragment = (BaseFragment) childFragment; if (childBaseFragment.isWaitingShowToUser()) { childBaseFragment.setWaitingShowToUser(false); childFragment.setUserVisibleHint(true); } } } } } else { // 将所有正在显示的子Fragment设置为隐藏状态,并设置一个等待显示标记 if (childFragmentList != null && childFragmentList.size() > 0) { for (Fragment childFragment : childFragmentList) { if (childFragment instanceof BaseFragment) { BaseFragment childBaseFragment = (BaseFragment) childFragment; if (childFragment.getUserVisibleHint()) { childBaseFragment.setWaitingShowToUser(true); childFragment.setUserVisibleHint(false); } } } } } } } public boolean isWaitingShowToUser() { return waitingShowToUser; } public void setWaitingShowToUser(boolean waitingShowToUser) { this.waitingShowToUser = waitingShowToUser; } }
本文内容来源于:https://blog.csdn.net/didayuye/article/details/101572984