Android仿今日头条N个fragment懒加载

龙旋

共 4665字,需浏览 10分钟

 ·

2021-09-01 12:07

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,这种情况,打断点调试,根本就没有调用setUserVisibleHint(),所以isVisible还是false,不执行lazyload方法。需要用FragmentPagerAdapter显式调用setUserVisibleHint()。



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


源码地址:
https://github.com/18380438200/LazyloadFragment-master


到这里就结束啦。
浏览 25
点赞
评论
收藏
分享

手机扫一扫分享

举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

举报