android Frament懒加载

541 阅读3分钟

文笔粗略 有更好的方法请进行评论谢谢    

  在我们使用viewpager+fragment中 由于相对于viewpager的预加载机制,导致当前fragment的后一个fragment进行加载,比较影响性能,为此, 百度许久 ,自己又是菜鸡 没办法,只能继续百度。

  • 百度上大部分的文章都是缺胳膊少腿的,很多也没有实例的应用,头疼头疼,难搞难搞啊,好在皇天不负有心人 找到了
@Override
public void setUserVisibleHint(boolean isVisibleToUser) {
    super.setUserVisibleHint(isVisibleToUser);
    if (isVisibleToUser) {
         //加载你的数据
    }
}

setUserVisibleHint 用户是否可见,我个人认为懒加载基于这个方法进行初始逻辑 这个方法有时候会在onCreate方法之前执行,也有可能在之后执行,所以一般都是在onCreate方法里面加入全局变量 判断onCreate方法是否执行完毕,代码如下

//页面是否创建完毕
 
private boolean isCreate = false;
 
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    View inflate = inflater.inflate(R.layout.fragment_police_quality, container, false);
    initView(inflate);
    isCreate = true;    return inflate;
}
 
 @Override
 public void setUserVisibleHint(boolean isVisibleToUser) {
     super.setUserVisibleHint(isVisibleToUser);
     if(isCreate && isVisibleToUser){
        //加载数据
     }
 }

 测试了一下 ,页面闪退 尴尬尴尬 惭愧惭愧 有负于江东父老 (mdzz怎么回事)修修改改几轮回 大功告成 下面就是主要代码 擦亮眼睛 当当当当当....look at

public abstract class BaseFragment extends Fragment {
    public View view;
 
    public Activity mContext;
    /**
     * 是否初始化过布局
     */
    protected boolean isViewInitiated;
    /**
     * 当前界面是否可见
     */
    protected boolean isVisibleToUser;
    /**
     * 是否加载过数据
     */
    protected boolean isDataInitiated;
 
    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        view = inflater.inflate(getLayoutId(), container, false);
        mContext = getActivity();
        this.initData(view);
        return view;
    }
 
    protected abstract int getLayoutId();
 
    @Override
    public void onActivityCreated(@Nullable Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        isViewInitiated=true;
        //加载数据
        prepareFetchData();
    }
 
    @Override
    public void setUserVisibleHint(boolean isVisibleToUser) {
        super.setUserVisibleHint(isVisibleToUser);
        this.isVisibleToUser = isVisibleToUser;
        if (isVisibleToUser) {
            prepareFetchData();
        }
    }
 
    public void prepareFetchData() {
        prepareFetchData(false);
    }
 
    /**
     * 判断懒加载条件
     *
     * @param forceUpdate 强制更新,好像没什么用?
     */
    public void prepareFetchData(boolean forceUpdate) {
        if (isVisibleToUser && isViewInitiated && (!isDataInitiated || forceUpdate)) {
            loadData();
            isDataInitiated = true;
        }
    }
 
    @Override
    public void startActivityForResult(Intent intent, int requestCode, @Nullable Bundle options) {
        if (Check.isFastClick()) {
            super.startActivityForResult(intent, requestCode, options);
        }
    }
 
 
    /**
     * 懒加载
     */
    protected abstract void loadData();
 
    protected abstract void initData(View view);
 
    @Override
    public void onDestroy() {
        super.onDestroy();
        this.view = null;
    }
}

使用示例(啊 完美 很爽)

public class TestFragment extends BaseFragment {
    @Override
    protected int getLayoutId() {
        return 0;
    }
 
    @Override
    protected void loadData() {
 
    }
 
    @Override
    protected void initData(View view) {
 
    }
}

stop,看到这里你以为问题就搞定了??? NONONO 还有一个小问题 viewpager的问题 啥问题呢 就是我们在滑动到第三个fragment的时候第一个不见了 也可能第二个不见了 ,最后连第三个也不见了,easy,那么我们就需要在viewpager的适配器里面做点手脚了

public class FragmentAdapter extends FragmentPagerAdapter {
 
    private List<Fragment> mFragments;
    private String[] title;
 
    public FragmentAdapter(FragmentManager fm, List<Fragment> fragments, String[] titles) {
        super(fm);
        this.mFragments = fragments;
        this.title = titles;
    }
 
    @Override
    public Fragment getItem(int position) {
        return mFragments.get(position);
    }
 
    @Override
    public int getCount() {
        return mFragments.size();
    }
 
    @Nullable
    @Override
    public CharSequence getPageTitle(int position) {
        return title[position];
    }
    //解决fragment滑动消失的问题
 
    @Override
    public void destroyItem(@NonNull ViewGroup container, int position, @NonNull Object object) {
 
    }
}

细心地我当然发现了那不一样 (别打脸) ,看到最后的方法了吧 重写它 删掉父类调来的方法,搞定 

destroyitem

一般来说,destroyitem在viewpager移除一个item时调用。 viewpage一般都会缓冲3个item,即一开始就会调用3次instantiateItem, 当向右滑动,到第3页时,第1页的item会被调用到destroyitem。