zoukankan      html  css  js  c++  java
  • Andorid上拉加载更多的几种实现方式

    1.前言

    Andriod中上拉加载更多的效果随处可见,因为一次性要展现的数据太多信息量太大的话,给用户的体验就很差(加载慢,界面卡顿、流量消耗大等),而加载更多可以控制每次加载条目的数量以达到快速加载,底部加载更多的方式就显得更人性化,今天就把用过的几种方式总结一下.

    2.上拉加载更多的实现方式

    1. ListView控件;作为一种传统列表展现的方式,ListView控件的addHeaderView(...)、addFooterView(...)方法很方便的支持头布局、脚布局,参数就是打气筒打出来的布局.这个很常见,也算是一种屡试不爽的方式.
    2. RecyclerView控件;它是Android5.0以后推出的新控件,在v7包中,可以完美向下兼容,相比于ListView可定制性更大.并且RecyclerView本身不参与任何视图相关的问题,它不关心如何将子View放在合适的位置,也不关心如何分割这些子View,更不关心每个子View各自的外观。更进一步来说就是RecyclerView它只负责回收和重用的工作,这也是它名字的由来.

         它并没有现成的下拉刷新和上拉加载的实现.下拉刷新可以配合SwipeRefreshView实现,这个较简单,来看下RecyclerView的加载更多实现方式.

               思路:recyclerView.addOnScrollListener(...),通过监听recyclerview的滚动状态,判断是滚动状态且最后可见条目是最后一条时,加载更多.

    final LinearLayoutManager layoutManager = new LinearLayoutManager(this);
    recyclerView = (RecyclerView) findViewById(R.id.recyclerView);
    recyclerView.setLayoutManager(layoutManager);
    recyclerView.setAdapter(adapter);
    recyclerView.setHasFixedSize(true);

    recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
    @Override
    public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
    super.onScrollStateChanged(recyclerView, newState);
    }

    @Override
    public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
    Log.d("==MainActivity==", "onScrolledStart");
    super.onScrolled(recyclerView, dx, dy);
    int lastVisibleItemPosition = layoutManager.findLastVisibleItemPosition();
    int count = adapter.getItemCount();
    if (lastVisibleItemPosition + 1 == count )
    {
    Log.d("==MainActivity==", "loading excute");
    if (!isLoading) {
    isLoading = true;
    handler.postDelayed(new Runnable() {
    @Override
    public void run() {
    isLoading = false;
    //加载更多数据
    addData();
    }
    }, 2000);

    }
    }

    }
    });
    public void addData() {
    adapter.addData(originalData);
    }
    
    
    public class RecyclerViewAdapter extends RecyclerView.Adapter<ViewHolder> {
    private static final int TYPE_ITEM = 0;
    private static final int TYPE_FOOTER = 1;
    private Context context;
    private List<Map<String,Object>> datas;


    public RecyclerViewAdapter(Context context) {
    this.context = context;

    datas = new ArrayList();
    }

    public void addData(List data) {
    datas.addAll(data);
    this.notifyItemRangeChanged(0, datas.size());
    }

    public interface OnItemClickListener {
    void onItemClicked(View view, int position);

    void onItemLongClicked(View view, int position);
    }

    private OnItemClickListener onItemClickListener;

    public void setOnItemClickListener(OnItemClickListener onItemClickListener) {
    this.onItemClickListener = onItemClickListener;
    }

    @Override
    public int getItemCount() {
    int aa = datas.size() == 0 ? 0 : datas.size() + 1;
    return aa;

    }

    @Override
    public int getItemViewType(int position) {
    if (position + 1 == getItemCount()) {
    return TYPE_FOOTER;
    } else {
    return TYPE_ITEM;
    }
    }

    @Override
    public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    //加载每个列表项
    if (viewType == TYPE_ITEM) {
    View view = LayoutInflater.from(context).inflate(R.layout.item_base, parent, false);
    return new ItemViewHolder(view);
    }
    if (viewType == TYPE_FOOTER) {
    View view = LayoutInflater.from(context).inflate(R.layout.item_foot, parent, false);
    return new FootViewHolder(view);
    }
    return null;
    }


    @Override
    public void onBindViewHolder(final ViewHolder holder, int position) {
    //加载每个列表项的数据
    if (holder instanceof ItemViewHolder) {

    Map<String, Object> listItem = datas.get(position);
    ((ItemViewHolder) holder).name.setText((String)listItem.get("personName") + " ------------" + String.valueOf(position));
    ((ItemViewHolder) holder).decs.setText((String)listItem.get("desc"));
    ((ItemViewHolder) holder).header.setImageResource((int)listItem.get("header"));
    if (onItemClickListener != null) {
    holder.itemView.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
    int position = holder.getLayoutPosition();
    onItemClickListener.onItemClicked(holder.itemView, position);
    }
    });

    holder.itemView.setOnLongClickListener(new View.OnLongClickListener() {
    @Override
    public boolean onLongClick(View v) {
    int position = holder.getLayoutPosition();
    onItemClickListener.onItemLongClicked(holder.itemView, position);
    return false;
    }
    });
    }
    }
    }

    static class ItemViewHolder extends ViewHolder {
    TextView name;
    TextView decs;
    ImageView header;

    public ItemViewHolder(View view) {
    super(view);
    decs = (TextView)view.findViewById(R.id.desc);
    name = (TextView)view.findViewById(R.id.name);
    header = (ImageView)view.findViewById(R.id.header);
    }
    }

    static class FootViewHolder extends ViewHolder {

    public FootViewHolder(View view) {
    super(view);
    }
    }
    }
    
    
    值得注意的就是getItemCount()方法返回的是数据总条目数+1,getItemViewType(int position) 方法返回当前position对应的条目类型,既然要底部加载更多,那就是2种不同的类型;
    onCreateViewHolder(ViewGroup parent, int viewType) 肯定是返回对应的这两种ViewHolder;onBindViewHolder方法就是依据holder决定绑定对应怎样的视图.
      3.对RecyclerView二次封装的开源框架;常用的有UltimateRecyclerView(解决RecyclerView下拉刷新,加载更多,增加头部,显示或隐藏工具栏等许多问题的知名开源框架)、
      PullLoadMoreRecyclerView(属性最全,实现了RecyclerView下拉刷新和上拉加载更多以及RecyclerView线性、网格、瀑布流效果)、SwipeToLoadLayout支持多种基于RecyclerView的上拉加载和下拉刷新样式;

      以
    PullLoadMoreRecyclerView为例子简单介绍其使用方式:
      build.gradle添加依赖:
       dependencies {
        compile 'com.wuxiaolong.pullloadmorerecyclerview:library:1.0.4'
       }
     
         设置线性布局(当然也有网格布局、瀑布流效果)
        mPullLoadMoreRecyclerView = (PullLoadMoreRecyclerView) view.findViewById(R.id.pullLoadMoreRecyclerView);
        mPullLoadMoreRecyclerView.setLinearLayout();
     
         绑定适配器,适配器的写法,这个没什么特别的,继承RecyclerView.Adapter就好了
       
       调用下拉刷新和加载更多(...啥也不说了,这接口暴露的多好...)
        mPullLoadMoreRecyclerView.setOnPullLoadMoreListener(new PullLoadMoreRecyclerView.PullLoadMoreListener() {
                @Override
                public void onRefresh() {//下拉刷新时调用
     
                }
     
                @Override
                public void onLoadMore() {//上拉加载更多时调用               
     
                }
            })
      mPullLoadMoreRecyclerView.setPullLoadMoreCompleted();//加载结束时调用
      此外还有很多个性化的接口方法暴露,很方便开发时使用.
    这里就不一一介绍了.具体可以去Github上搜索.

    3.总结
    按时间来说,我用得最多的是ListView,但是头布局越来越多后,position的转换显得很麻烦,而且recyclerview的缓存和回收机制更高效,recyclerview早就挡不住了,
    listview和Gridview正在被recycleview替代,了解一些优秀的开源框架对开发事半功倍,但是我要强调的是这些框架的具体实现原理如果搞懂的话,可以形成自己的东西,有时间自己也能写出高效的框架来.后面也会深入理解.






    
    
     
  • 相关阅读:
    openstack Rocky系列之Cinder:(一)Cinder服务启动
    openstack Rocky系列之keystone:(二)keystone中API注册
    openstack Rocky系列之keystone:(一)keystone的启动
    Ubuntu16.04搭建kubernetes v1.11.2集群
    HIVE创建分区,添加数据
    深度优先和广度优先
    创建appium容器以及设置appium容器连接安卓模拟器
    appium+fiddler——douyin小爬虫
    命令_查看端口占用情况 netstat -ano|findstr PID
    aapt 命令查看apk包名、主activity、版本等信息
  • 原文地址:https://www.cnblogs.com/fuyaozhishang/p/6624833.html
Copyright © 2011-2022 走看看