ViewPager与Fragment结合使用时遇到的坑(notifyDataSetChanged()无效, 懒加载)

来源:互联网 发布:数码宝贝3 知乎 编辑:程序博客网 时间:2024/05/21 00:20

一. 当与Adapter绑定的List发生改变时, notifyDataSetChanged()方法无效

当我们调用adapter.notifyDataSetChanged()时, 正常情况下会将ViewPager中正在执行和已经预加载的Fragment全部Destroy, 然后重新执行ViewPager需要的Fragment的生命周期

问题描述: 一般Adapter的List添加了一个Item, 调用adapter.notifyDataSetChanged()时, ViewPager是会随之改变的, 不过当移除了List中的一个Item时, 再调用adapter.notifyDataSetChanged()时, 你会惊喜的发现ViewPager没有任何变化!

解决方法:
1.将我们定义的ViewPager的Adapter类的继承父类修改为FragmentStatePagerAdapter
2.重写getItemPosition方法, 强制其返回PagerAdapter.POSITION_NONE

public class ViewPagerAdapter extends FragmentStatePagerAdapter {    private List<Fragment> mList;    public ActivityMainAdapter(FragmentManager fm , List<Fragment> mList) {        super(fm);        this.mList = mList;    }    @Override    public Fragment getItem(int position) {        return mList.get(position);    }    @Override    public int getCount() {        return mList.size();    }    @Override    public int getItemPosition(Object object) {        return PagerAdapter.PITION_NONE    }}

二. ViewPager的懒加载

ViewPager默认是具有预加载功能的, 通过mViewPager.setOffscreenPageLimit(1)通过该方法可以指定ViewPager预加载的数目, 1代表的是除了当前需要显示的Fragment以外, 该ViewPager 还会预加载其左右两侧各一个Fragment以达到流畅滑动的目的, 这个功能是关闭不了的( 除非重写一个ViewPager ), 且在一般情况下也不建议关闭. 若不想重写源码, 就需要从Fragment中的setUserVisibleHint方法开始操作了 .

@Overridepublic void setUserVisibleHint(boolean isVisibleToUser) {    super.setUserVisibleHint(isVisibleToUser);}

当Fragment可视状态发生改变时会调用该方法, 我们可以利用其实现懒加载的功能
注意!!!!!该方法在Fragment的生命周期开始之前也会被调用, 此时Fragment的生命周期还没有开始运行, 所有的控件均未初始化, 若此时给控件赋值, 程序将直接Crash! 所以正确的撸法应是以下这样的

/** * Created by FrankChoo on 2017/6/11. */public abstract class LazyFragment extends Fragment {    private boolean isVisibleToUser = false;//Fragment页面是否可见    private boolean isViewInitiated = false;//控件是否完成初始化    /**     * 执行时机:     * 1. 在Fragment生命周期的onAttach方法开始之前执行     * 2. 在Fragment可视状态发生改变时执行     */    @Override    public void setUserVisibleHint(boolean isVisibleToUser) {        super.setUserVisibleHint(isVisibleToUser);        this.isVisibleToUser = isVisibleToUser;        prepareForLazyWork();    }    /**     * 执行时机: 该方法在Fragment生命周期中的onCreateView方法之后执行     *          此时控件均已经初始化, 比较适合进行懒加载     */    @Override    public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {        super.onViewCreated(view, savedInstanceState);        isViewInitiated = true;//此时Fragment已经初始化完毕, 控件已可用, 不会出现空指针异常        prepareForLazyWork();    }    /**     * 准备执行懒加载任务     */    private void prepareForLazyWork() {        //只有当Fragment可见且控件均已初始化完成时执行懒加载的方法        if (isVisibleToUser && isViewInitiated) {            doLazyWork();        }    }    /**     * 执行懒加载任务     */    protected abstract void doLazyWork();    @Override    public void onDestroy() {        isVisibleToUser = false;        isViewInitiated = false;        super.onDestroy();    }}
原创粉丝点击