Android仿今日头条多个fragment懒加载的实现
前言
最近有时间,所以我又双叒叕推新一篇文章了,fragment懒加载实现虽然是个小模块,但做过的人都有体会,通常并不会轻易就成功了的,让你辗转反侧,彻夜难眠,绵绵无绝期。我就按照今日头条的样式做了一个懒加载功能。文章到一半会解释大家可能遇到的不加载数据了的坑,先不剧透。
fragment的生命周期回顾
这里是今日头条效果:
自制效果,有图有真相:
实现思路:
使用fragment类自带方法setuservisiblehint()判断当前fragment是否对用户可见,根据回调的isvisibletouser参数来进行相关的逻辑判断。重写该方法,创建变量isvisible拿到是否可见标志。
但是直接根据isvisible判断就加载数据,可能oncreateview()方法并未执行完毕,此时就会出现nullpointerexception空指针异常。所以就需要满足控件初始化完成,用户可见,才能加载数据。
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,用pageradapter,打断点调试,根本就没有调用setuservisiblehint(),所以isvisible还是false,不执行lazyload方法。需要用fragmentpageradapter显示调用setuservisiblehint()。
换上fragmentpageradapter后调试,调用setuservisiblehint,isvisible为ture了。
总结
以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对的支持。