fragment 懒加载保证展示的时候获取数据并且只获取一次,删除后清楚缓存的终极解决方案

在开发中经常用的Fragment+ViewPager的情况,但是viewPager的缓存机制导致至少会提前加载一个邻近的Fragment,导致数据重复加载。此时的解决办法是写一个基类BaseLasyFragment来处理,具体实现如下:

public abstract class BaseLazyFragment extends Fragment {

    /**
     * Log tag
     */
    protected static String TAG_LOG = null;

    /**
     * context
     */
    protected Context mContext = null;

    /**
     * 视图是否已经初初始化
     */
    protected boolean isInit = false;
    protected boolean isLoad = false;
    protected final String TAG = "LazyLoadFragment";
    private View view;

    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);
        mContext = activity;
    }

    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        if (getContentViewLayoutID() != 0) {
            view = inflater.inflate(getContentViewLayoutID(), container, false);
        } else {
            view = super.onCreateView(inflater, container, savedInstanceState);
        }
        return view;
    }

    @Override
    public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        initViewsAndEvents(savedInstanceState);

        isInit = true;
        /**初始化的时候去加载数据**/
        isCanLoadData();
    }

    @Override
    public void onDestroyView() {
        super.onDestroyView();
        isInit = false;
        isLoad = false;
    }

    @Override
    public void onDetach() {
        super.onDetach();
        // for bug ---> java.lang.IllegalStateException: Activity has been destroyed
        try {
            Field childFragmentManager = Fragment.class.getDeclaredField("mChildFragmentManager");
            childFragmentManager.setAccessible(true);
            childFragmentManager.set(this, null);

        } catch (NoSuchFieldException e) {
            throw new RuntimeException(e);
        } catch (IllegalAccessException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 视图是否已经对用户可见,系统的方法
     */
    @Override
    public void setUserVisibleHint(boolean isVisibleToUser) {
        super.setUserVisibleHint(isVisibleToUser);
        isCanLoadData();
    }

    /**
     * 是否可以加载数据
     * 可以加载数据的条件:
     * 1.视图已经初始化
     * 2.视图对用户可见
     */
    private void isCanLoadData() {
        if (!isInit) {
            return;
        }

        if (getUserVisibleHint()) {
            lazyLoad();
            isLoad = true;
        } else {
            if (isLoad) {
                stopLoad();
            }
        }
    }

    /**
     * 当视图初始化并且对用户可见的时候去真正的加载数据
     */
    protected abstract void lazyLoad();

    /**
     * 当视图已经对用户不可见并且加载过数据,如果需要在切换到其他页面时停止加载数据,可以调用此方法
     */
    public void stopLoad() {
    }


    /**
     * bind layout resource file
     *
     * @return id of layout resource
     */
    protected abstract int getContentViewLayoutID();

    /**
     * when event comming
     *
     * @param eventCenter
     */
    protected abstract void onHandleEventMessage(EventCenter eventCenter);

    /**
     * init all views and add events
     */
    protected abstract void initViewsAndEvents(Bundle savedInstanceState);
}

然后在自定义Fragment继承BaseLasyFragment ,复写lasyLoad()方法即可,在此方法中实现展示页面时数据请求的操作,能保证只有在展示页面的时候才进行数据请求。

如果想在Fragment隐藏的时候取消数据请求,可以复写stopLoad()方法进行处理。

 

 

有时候需要每次在Fragment页面展示的时候添加一个Fragment页面列表,第二次进入添加列表的时候,会导致已经添加过的列表还存在,不管是调用viewPager的removeAllViews()还是清空adapter,都无作用,原因是FragmentPagerAdatper添加过的Fragment都在内存中缓存了,除非退出APP,否则一直存在,此时解决办法是改用继承FragmentStatePagerAdapter,并且复写以下方法,然后再调用viewPager的removeAllViews()和adapter的notifyDataSetChanged(当然需要清空列表)即可

public int getItemPosition(Object item) {
        return POSITION_NONE;
    }

结合上面的懒加载基类,可以在stopLoad()回调中进行清空缓存操作。切记不要放在 lasyLoad()方法里,因为每次新增Fragment的时候,lasyLoad()是拿不到之前隐藏掉的Fragment中的数据的,所以在隐藏的时候进行清空缓存是可以保证清楚的干干净净的。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值