仿今日头条N个fragment懒加载

作者: 奔跑吧李博 | 来源:发表于2017-12-01 13:16 被阅读410次

    啊哈,我又双叒叕推新一篇文章了,fragment懒加载实现虽然是个小模块,但做过的人都有体会,通常并不会轻易就成功了的,让你辗转反侧,彻夜难眠,绵绵无绝期。我就按照今日头条的样式做了一个懒加载功能。文章到一半会解释大家可能遇到的不加载数据了的坑,先不剧透。

    github代码直通车

    这里是今日头条效果:


    giphy.gif

    自制效果,有图有真相:


    giphy.gif

    实现思路:

    使用Fragment类自带方法setUserVisibleHint()判断当前fragment是否对用户可见,根据回调的isVisibleToUser参数来进行相关的逻辑判断。重写该方法,创建变量isVisible拿到是否可见标志。

    但是直接根据isVisible判断就加载数据,可能onCreateView()方法并未执行完毕,此时就会出现NullPointerException空指针异常。所以就需要满足控件初始化完成,用户可见,才能加载数据。

    image.png
    LazyloadFragment懒加载fragment实现:
    public abstract class LazyloadFragment extends Fragment {
        protected View rootView;
        private boolean isInitView = false;
        private boolean isVisible = false;
    
        @Nullable
        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
            rootView = inflater.inflate(setContentView(), container, false);
            init();
            isInitView = true;
            isCanLoadData();
            return rootView;
        }
    
        @Override
        public void setUserVisibleHint(boolean isVisibleToUser) {
            super.setUserVisibleHint(isVisibleToUser);
    
            //isVisibleToUser这个boolean值表示:该Fragment的UI 用户是否可见,获取该标志记录下来
            if(isVisibleToUser){
                isVisible = true;
                isCanLoadData();
            }else{
                isVisible = false;
            }
        }
    
        private void isCanLoadData(){
            //所以条件是view初始化完成并且对用户可见
            if(isInitView && isVisible ){
                lazyLoad();
    
                //防止重复加载数据
                isInitView = false;
                isVisible = false;
            }
        }
    
        /**
         * 加载页面布局文件
         * @return
         */
        protected abstract int setContentView();
    
        /**
         * 让布局中的view与fragment中的变量建立起映射
         */
        protected abstract void init();
    
        /**
         * 加载要显示的数据
         */
        protected abstract void lazyLoad();
    
    }
    
    

    子fragment加载数据:

    public class PageFragment extends LazyloadFragment implements XRecyclerView.LoadingListener {
        private CommonAdapter<String> adapter;
        private ArrayList<String> datas = new ArrayList<>();
        private XRecyclerView recyclerView;
        private Handler handler = new Handler();
    
        @Override
        public int setContentView() {
            return R.layout.fragment_page;
        }
    
    
        @Override
        public void init() {
            recyclerView = rootView.findViewById(R.id.recyclerview);
            recyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
            adapter = new CommonAdapter<String>(getActivity(),R.layout.item,datas) {
                @Override
                protected void convert(ViewHolder holder, String s, int position) {
    
                }
            };
            recyclerView.setAdapter(adapter);
            recyclerView.setPullRefreshEnabled(true);
            recyclerView.setLoadingListener(this);
    
        }
    
        @Override
        public void lazyLoad() {
            recyclerView.refresh();
        }
    
        @Override
        public void onRefresh() {
            handler.postDelayed(new Runnable() {
                @Override
                public void run() {
                    recyclerView.refreshComplete();
                    for(int i=0;i<10;i++){
                        datas.add("");
                    }
                    adapter.notifyDataSetChanged();
                }
            },500);
        }
    
        @Override
        public void onLoadMore() {
    
        }
    }
    

    最后Mainactivity代码:

    public class MainActivity extends AppCompatActivity {
        private TabLayout tabLayout;
        private String[] topics = new String[]{"推荐","热点","北京","视频","社会","图片"};
        private ViewPager viewPager;
        private ArrayList<Fragment> fragments = new ArrayList<>();
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
            setContentView(R.layout.activity_main);
    
            init();
        }
    
        private void init() {
            viewPager = (ViewPager) findViewById(R.id.viewpager);
            tabLayout = (TabLayout) findViewById(R.id.tablayout);
            viewPager.setOffscreenPageLimit(3);
    
            for(int i=0;i<topics.length;i++){
                tabLayout.addTab(tabLayout.newTab());
                fragments.add(new PageFragment());
            }
            viewPager.setAdapter(new FmPagerAdapter(fragments,getSupportFragmentManager()));
            tabLayout.setupWithViewPager(viewPager);
    
            for (int j = 0; j < topics.length; j++) {
                tabLayout.getTabAt(j).setText(topics[j]);
            }
        }
    }
    
    坑来了

    大家千篇一律地说用setUserVisibleHint()方法就可以了,但是没有说这个问题。是不是用了Lazyloadfragment不加载数据了?因为你的Viewpager用的是PagerAdapter,这种情况,打断点调试,根本就没有调用setUserVisibleHint(),所以isVisible还是false,不执行lazyload方法。需要用FragmentPagerAdapter显式调用setUserVisibleHint()。


    PagerAdapter调试

    换上FragmentPagerAdapter后调试,调用setUserVisibleHint,isVisible为ture了。


    FragmentPagerAdapter调试

    好了,完整代码在上面github地址,不要走开,广告之后马上下一集!

    相关文章

      网友评论

      本文标题:仿今日头条N个fragment懒加载

      本文链接:https://www.haomeiwen.com/subject/zhkbbxtx.html