优秀的RecyclerView框架加下拉刷新,上拉加载

//首先在progect下加依赖
buildscript {
    
    repositories {
        google()
        jcenter()
        mavenCentral() // add repository
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:3.0.1'

        classpath 'org.greenrobot:greendao-gradle-plugin:3.2.2' // add plugin
        // NOTE: Do not place your application dependencies here; they belong
        // in the individual module build.gradle files
    }
}

allprojects {
    repositories {
        google()
        jcenter()
        maven { url "https://jitpack.io" }
    }
}

//再在module下加依赖
 

implementation 'com.github.CymChad:BaseRecyclerViewAdapterHelper:2.9.30'//万能RecyclerView适配器


implementation 'com.android.support:recyclerview-v7:26.1.0'



implementation 'com.squareup.picasso:picasso:2.5.2'
implementation 'com.scwang.smartrefresh:SmartRefreshLayout:1.0.5.1'
implementation 'com.scwang.smartrefresh:SmartRefreshHeader:1.0.5.1'//没有使用特殊Header,可以不加这行

 

 

   

        

        

        

    

业务(我的业务中,不进行上拉加载更多)

 
  1. 
        mRefreshLayout.setOnRefreshListener(new OnRefreshListener(){
    
    @Override
    
    public void onRefresh(RefreshLayout refreshlayout){
    
            requestData();
    
            }
    
            });
    
            mRefreshLayout.setOnLoadmoreListener(new OnLoadmoreListener(){
    
    @Override
    
    public void onLoadmore(RefreshLayout refreshlayout){
    
            mRefreshLayout.finishLoadmore(2000);
    
            }
    
            });

     


 

属性 Attributes

名称-name 格式-format 描述-description
srlPrimaryColor color 主题颜色
srlAccentColor color 强调颜色
srlReboundDuration integer 释放后回弹动画时长
srlHeaderHeight dimension Header的标准高度
srlFooterHeight dimension Footer的标准高度
srlDragRate float 显示拖动高度/真实拖动高度(默认0.5,阻尼效果)
srlHeaderMaxDragRate float Header最大拖动高度/Header标准高度(默认2,要求>=1)
srlFooterMaxDragRate float Footer最大拖动高度/Footer标准高度(默认2,要求>=1)
srlEnableRefresh boolean 是否开启下拉刷新功能(默认true)
srlEnableLoadmore boolean 是否开启加上拉加载功能(默认true)
srlEnableHeaderTranslationContent boolean 拖动Header的时候是否同时拖动内容(默认true)
srlEnableFooterTranslationContent boolean 拖动Footer的时候是否同时拖动内容(默认true)
srlEnablePreviewInEditMode boolean 是否在编辑模式时显示预览效果(默认true)
srlDisableContentWhenRefresh boolean 是否在刷新的时候禁止内容的一切手势操作(默认false)
srlDisableContentWhenLoading boolean 是否在加载的时候禁止内容的一切手势操作(默认false)

方法 Method

名称-name 格式-format 描述-description
setPrimaryColors colors 主题\强调颜色
setPrimaryColorsId colors 主题\强调颜色资源Id
setReboundDuration integer 释放后回弹动画时长
setHeaderHeight dimension Header的标准高度(px/dp 两个版本)
setFooterHeight dimension Footer的标准高度(px/dp 两个版本)
setDragRate float 显示拖动高度/真实拖动高度(默认0.5,阻尼效果)
setHeaderMaxDragRate float Header最大拖动高度/Header标准高度(默认2,要求>=1)
setFooterMaxDragRate float Footer最大拖动高度/Footer标准高度(默认2,要求>=1)
setEnableRefresh boolean 是否开启下拉刷新功能(默认true)
setEnableLoadmore boolean 是否开启加上拉加载功能(默认true)
setEnableHeaderTranslationContent boolean 拖动Header的时候是否同时拖动内容(默认true)
setEnableFooterTranslationContent boolean 拖动Footer的时候是否同时拖动内容(默认true)
setEnableAutoLoadmore boolean 是否监听列表滚动到底部时触发加载事件
setDisableContentWhenRefresh boolean 是否在刷新的时候禁止内容的一切手势操作(默认false)
setDisableContentWhenLoading boolean 是否在加载的时候禁止内容的一切手势操作(默认false)
setReboundInterpolator Interpolator 设置回弹动画的插值器
setRefreshHeader RefreshHeader 设置指定的Header
setRefreshFooter RefreshFooter 设置指定的Footer
setOnRefreshListener OnRefreshListener 设置刷新监听器
setOnLoadmoreListener OnLoadmoreListener 设置加载监听器
setOnRefreshLoadmoreListener OnRefreshLoadmoreListener 同时设置上面两个监听器
setOnMultiPurposeListener OnMultiPurposeListener 设置多功能监听器
setLoadmoreFinished boolean 设置全部数据加载完成,之后不会触发加载事件
finishRefresh (int delayed) 完成刷新,结束刷新动画
finishLoadmore (int delayed) 完成加载,结束加载动画
getRefreshHeader RefreshHeader 获取Header
getRefreshFooter RefreshFooter 获取Footer
getState RefreshState 获取当前状态
isRefreshing boolean 是否正在刷新
isLoading boolean 是否正在加载
autoRefresh (int delayed) 触发自动刷新
autoLoadmore (int delayed) 触发自动加载

 

 

package db.lanxing.damexshixu.ui.frament2;

import android.Manifest;
import android.content.Intent;
import android.os.Build;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v4.app.ActivityCompat;
import android.support.v4.app.Fragment;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.StaggeredGridLayoutManager;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.Toast;

import com.chad.library.adapter.base.BaseQuickAdapter;
import com.recker.flybanner.FlyBanner;
import com.scwang.smartrefresh.layout.footer.ClassicsFooter;
import com.squareup.picasso.Picasso;
import com.umeng.socialize.ShareAction;
import com.umeng.socialize.UMAuthListener;
import com.umeng.socialize.UMShareAPI;
import com.umeng.socialize.UMShareListener;
import com.umeng.socialize.bean.SHARE_MEDIA;
import com.umeng.socialize.media.UMImage;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.Unbinder;
import db.lanxing.damexshixu.R;
import db.lanxing.damexshixu.adapter.MyRecAdapter;
import db.lanxing.damexshixu.dao.MyBeanDao;
import db.lanxing.damexshixu.data.ApiService;
import db.lanxing.damexshixu.data.App;
import db.lanxing.damexshixu.data.Bean;
import db.lanxing.damexshixu.data.Constans;
import db.lanxing.damexshixu.data.MyBean;
import db.lanxing.damexshixu.ui.activity.MainActivity;
import retrofit2.Retrofit;
import retrofit2.adapter.rxjava.RxJavaCallAdapterFactory;
import retrofit2.converter.gson.GsonConverterFactory;
import rx.Observer;
import rx.android.schedulers.AndroidSchedulers;
import rx.schedulers.Schedulers;

import android.content.Intent;
import android.graphics.drawable.ColorDrawable;
import android.os.Bundle;
import android.os.Handler;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.StaggeredGridLayoutManager;
import android.support.v7.widget.Toolbar;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
import android.widget.PopupWindow;
import android.widget.TextView;
import android.widget.Toast;

import com.android.volley.AuthFailureError;
import com.android.volley.Request;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.StringRequest;
import com.android.volley.toolbox.Volley;
import com.chad.library.adapter.base.BaseQuickAdapter;
import com.google.gson.Gson;
import com.scwang.smartrefresh.layout.SmartRefreshLayout;
import com.scwang.smartrefresh.layout.api.RefreshLayout;
import com.scwang.smartrefresh.layout.constant.SpinnerStyle;
import com.scwang.smartrefresh.layout.footer.BallPulseFooter;
import com.scwang.smartrefresh.layout.header.ClassicsHeader;
import com.scwang.smartrefresh.layout.listener.OnLoadMoreListener;
import com.scwang.smartrefresh.layout.listener.OnRefreshListener;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import butterknife.BindView;
import butterknife.ButterKnife;
import db.myrecy.R;
import db.myrecy.adapter.MyAdapter;
import db.myrecy.utils.dao.StudentsDao;
import db.myrecy.data.bean.Bean;
import db.myrecy.data.bean.MyBean;
import db.myrecy.data.common.Constant;
import db.myrecy.utils.dbutil.App;

public class MainActivity extends AppCompatActivity {
    @BindView(R.id.tbr)
    Toolbar tbr;
    @BindView(R.id.rcw)
    RecyclerView rcw;
    @BindView(R.id.refreshLayout)
    SmartRefreshLayout refreshLayout;
    private List list;
    private List myBeans = new ArrayList<>();
    private MyAdapter adapter;
    private int size;
    private int count;
    private Intent intent;
    private StudentsDao dao;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ButterKnife.bind(this);
        dao = App.getDB(this);
        initData();
        initDataHttp();
    }

    private void initDataHttp() {
        Volley.newRequestQueue(this).add(new StringRequest(Request.Method.POST, Constant.URL, new Response.Listener() {
            @Override
            public void onResponse(String response) {
            }
        }, new Response.ErrorListener() {
            @Override
            public void onErrorResponse(VolleyError error) {
            }
        }) {
            @Override
            protected Map getParams() throws AuthFailureError {
                return super.getParams();
            }
        });
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        if (item.getItemId() == 1) {
            startActivityForResult(new Intent(MainActivity.this, AddActivity.class), 11);
        }
        return super.onOptionsItemSelected(item);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        menu.add(1, 1, 1, "添加数据");
        return super.onCreateOptionsMenu(menu);
    }

    Handler handler = new Handler();
    Runnable runnable = new Runnable() {
        @Override
        public void run() {
            if (adapter == null) {
                Toast.makeText(MainActivity.this, "没有数据数据", Toast.LENGTH_SHORT).show();
                return;
            } else {
                count = adapter.getItemCount();
            }
            if (adapter.getItemCount() == size) {
                Toast.makeText(MainActivity.this, "没有更多了", Toast.LENGTH_SHORT).show();
            }
            if (count + 5 < size) {
                for (int i = count; i < count + 5; i++) {
                    getMyBean(i);
                }
            } else {
                for (int i = count; i < size; i++) {
                    getMyBean(i);
                }
            }
            adapter.notifyDataSetChanged();
        }
    };
    private List images;

    private void initData() {
        setSupportActionBar(tbr);
        rcw.setLayoutManager(new StaggeredGridLayoutManager(2, StaggeredGridLayoutManager.VERTICAL));
        Volley.newRequestQueue(this).add(new StringRequest(Constant.URL, new Response.Listener() {
            @Override
            public void onResponse(String response) {
                list = new Gson().fromJson(response, Bean.class).getResults();
                size = list.size();
                for (int i = count; i < 2; i++) {
                    getMyBean(i);
                }
                adapter = new MyAdapter(R.layout.item, myBeans);
                rcw.setAdapter(adapter);
                initListener();
            }
        }, new Response.ErrorListener() {
            @Override
            public void onErrorResponse(VolleyError error) {
            }
        }));
       
简单的使用

public class Adapter1  extends BaseQuickAdapter{

    Context mcontext;

    public Adapter1(Context context,int layoutResId, @Nullable List data) {
        super(layoutResId, data);
        mcontext=context;
    }

    @Override
    protected void convert(BaseViewHolder helper, Student item) {

        helper.setText(R.id.student_name,item.getName())
                .setText(R.id.student_age,item.getAge()+"")
                .setText(R.id.student_address,item.getAddress());

        Glide.with(mcontext).load(item.getIcon()).into((ImageView) helper.getView(R.id.student_icon));
    }

}
 

从上文中的实例代码我们可以看出以下几点:

1、使用: 首先需要继承BaseQuickAdapter,然后BaseQuickAdapter 《Bean,BaseViewHolder》 第一个泛型Bean是数据实体类型,第二个BaseViewHolder是ViewHolder其目的是为了支持扩展ViewHolder。

2、赋值:可以直接使用viewHolder对象点相关方法通过传入viewId和数据进行,方法支持链式调用。如果是加载网络图片或自定义view可以通过viewHolder.getView(viewId)获取该控件。
添加Item事件

item的点击事件和长按事件已经封装到adapter里面,只需要在使用的时候用就可以了。

   adapter.setOnItemClickListener(new BaseQuickAdapter.OnItemClickListener() {
            @Override
            public void onItemClick(BaseQuickAdapter adapter, View view, int position) {
                Toast.makeText(CommonAdapterActivity.this, "点击了item", Toast.LENGTH_SHORT).show();
            }
        }); 

Item的长按事件

adapter.setOnItemLongClickListener(new BaseQuickAdapter.OnItemLongClickListener() {
            @Override
            public boolean onItemLongClick(BaseQuickAdapter adapter, View view, int position) {
                  Toast.makeText(CommonAdapterActivity.this, "长按了item", Toast.LENGTH_SHORT).show();
                return false;
            }
        });
 

注意:嵌套recycleView的情况下需要使用你使用 adapter. setOnItemClickListener 来设置点击事件,如果使用recycleView.addOnItemTouchListener会累计添加的。
添加Item子控件点击事件

首先在adapter的convert方法里面通过viewHolder.addOnClickListener绑定一下的控件id,

    @Override
    protected void convert(BaseViewHolder helper, Student item) {

        helper.setText(R.id.student_name,item.getName())
                .setText(R.id.student_age,item.getAge()+"")
                .setText(R.id.student_address,item.getAddress())
                .addOnClickListener(R.id.student_icon)
                .addOnClickListener(R.id.student_name)
                .addOnLongClickListener(R.id.student_address);

        Glide.with(mcontext).load(item.getIcon()).into((ImageView) helper.getView(R.id.student_icon));
    }
 

然后在设置子控件点击事件

  adapter.setOnItemChildClickListener(new BaseQuickAdapter.OnItemChildClickListener() {
            @Override
            public void onItemChildClick(BaseQuickAdapter adapter, View view, int position) {

                switch (view.getId()) {

                    case R.id.student_icon:
                        //获取其他控件,如下,获取student_name
                        TextView textView=(TextView) adapter.getViewByPosition(recycleview, position, R.id.student_name);
                        Toast.makeText(CommonAdapterActivity.this, "点击"+textView.getText().toString()+"的头像", Toast.LENGTH_SHORT).show();
                        break;

                    case R.id.student_name:
                        Toast.makeText(CommonAdapterActivity.this, "点击了名字", Toast.LENGTH_SHORT).show();
                        break;
                }
            }
        }); 

然后在设置子控件长按事件

  adapter.setOnItemChildLongClickListener(new BaseQuickAdapter.OnItemChildLongClickListener() {
            @Override
            public boolean onItemChildLongClick(BaseQuickAdapter adapter, View view, int position) {

                if (view.getId() == R.id.student_address)
                    Toast.makeText(CommonAdapterActivity.this, "长按了address", Toast.LENGTH_SHORT).show();
                return false;
            }
        });
 
注意:设置子控件的事件,如果不在adapter中绑定,点击事件无法生效,因为无法找到你需要设置的控件。
如果需要获取item中其他控件,上述代码有表现, adapter.getViewByPosition()方法进行初始化

TextView textView=(TextView) adapter.getViewByPosition(recycleview, position, R.id.student_name);
 
ps:如果有header的话需要处理一下position加上 headerlayoutcount。即如果header有的话,postion的点击postion实际上为postion+headerlayoutcount.
动画

开启动画(默认为渐显效果)

adapter.openLoadAnimation(); 

默认提供5种方法(渐显、缩放、从下到上,从左到右、从右到左)

    public static final int ALPHAIN = 0x00000001;
    public static final int SCALEIN = 0x00000002;
    public static final int SLIDEIN_BOTTOM = 0x00000003;
    public static final int SLIDEIN_LEFT = 0x00000004;
    public static final int SLIDEIN_RIGHT = 0x00000005;
 

切换动画

quickAdapter.openLoadAnimation(BaseQuickAdapter.ALPHAIN); 

自定义动画

quickAdapter.openLoadAnimation(new BaseAnimation() {
                            @Override
                            public Animator[] getAnimators(View view) {
                                return new Animator[]{
                                        ObjectAnimator.ofFloat(view, "scaleY", 1, 1.1f, 1),
                                        ObjectAnimator.ofFloat(view, "scaleX", 1, 1.1f, 1)
                                };
                            }
                        });
 

动画默认只执行一次,如果想重复执行可设置

mQuickAdapter.isFirstOnly(false); 

因为有些人不希望第一页看到动画,或者说希望前几个条目加载不需要有动画,所以可以

设置不显示动画数量

adapter.setNotDoAnimationCount(count); 

添加头部、尾部

mQuickAdapter.addHeaderView(getView());
mQuickAdapter.addFooterView(getView());
 
删除指定view

mQuickAdapter.removeHeaderView(getView);
mQuickAdapter.removeFooterView(getView); 

删除所有

mQuickAdapter.removeAllHeaderView();
mQuickAdapter.removeAllFooterView();  
默认出现了头部就不会显示Empty,和尾部,配置以下方法也支持同时显示:

setHeaderAndEmpty
setHeaderFooterEmpty
 

默认头部尾部都是占满一行,如果需要不占满可以配置:

setHeaderViewAsFlow
setFooterViewAsFlow 

加载更多

此adapter封装加载更多其实并不好用,因此我更建议采用传统的根据recyclerview判断item位置进行判断,自动加载更多

  recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
            @Override
            public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
                super.onScrollStateChanged(recyclerView, newState);
                lastVisibleItem = linearLayoutManager.findLastVisibleItemPosition();
                firstVisibleItem=linearLayoutManager.findFirstVisibleItemPosition();

                if (newState == RecyclerView.SCROLL_STATE_IDLE&&linearLayoutManager.getItemCount() >0&&lastVisibleItem + 1 == linearLayoutManager.getItemCount()) {
                        new Handler().postDelayed(() -> loadData(),300) ;
                }
            }

            @Override
            public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
                super.onScrolled(recyclerView, dx, dy);
                lastVisibleItem = linearLayoutManager.findLastVisibleItemPosition();
                firstVisibleItem=linearLayoutManager.findFirstVisibleItemPosition();
               }
        }); 

 LinearLayoutManager layoutManager = (LinearLayoutManager) recyclerView.getLayoutManager();  
  ```

屏幕中最后一个可见子项的position 
 
int lastVisibleItem = layoutManager.findLastVisibleItemPosition();
“`
//当前屏幕所看到的子项个数

  layoutManager.getChildCount();  

 

//当前RecyclerView的所有子项个数

 layoutManager.getItemCount();  

   

//RecyclerView的滑动状态

recyclerView.getScrollState(); 

 

 

    


        sw.setRefreshHeader(new DeliveryHeader(this));//降落伞
//        sw.setRefreshHeader(new WaveSwipeHeader(this));//水滴下落
//        sw.setRefreshHeader(new WaterDropHeader(this));//水滴上浮
//        sw.setRefreshHeader(new FunGameBattleCityHeader(this));//打仗坦克小游戏
//        sw.setRefreshHeader(new FunGameHitBlockHeader(this));//弹弹球
//        sw.setRefreshHeader(new DropboxHeader(this));//掉落盒子
         sw.setRefreshHeader(new BezierRadarHeader(this));//贝塞尔雷达



//        sw.setRefreshFooter(new BallPulseFooter(this).setSpinnerStyle(SpinnerStyle.Scale));//三点移动
        sw.setRefreshFooter(new BallPulseFooter(this));


        sw.setReboundDuration(100);//回弹
        sw.setScrollBarFadeDuration(100);//滚动条消失


 sm.setRefreshHeader(new ClassicsHeader(this));
//        设置 Footer 为 球脉冲 样式 
         sm.setRefreshFooter(new BallPulseFooter(this).setSpinnerStyle(SpinnerStyle.Scale));
         sm.setRefreshFooter(new ClassicsFooter(this).setSpinnerStyle(SpinnerStyle.Scale));
         sm.setReboundDuration(100);
         sm.setScrollBarFadeDuration(100);
         sm.setOnRefreshListener(new OnRefreshListener() {
@Override
public void onRefresh(sm sm) {
        handler.postDelayed(runnable, 10);
        sm.finishRefresh(1000/*,false*/);
//                传入false表示刷新失败 
        }
        });
        sm.setOnLoadMoreListener(new OnLoadMoreListener() {
@Override
public void onLoadMore(sm sm) {
        handler.postDelayed(runnable, 10);
        Toast.makeText(MainActivity.this, "加载完成", Toast.LENGTH_SHORT).show();
        sm.finishLoadMore(1000/*,false*/);
//                        传入false表示加载失败 
        }
        });
        }

 

    private void initListener() {
        adapter.setOnItemClickListener(new BaseQuickAdapter.OnItemClickListener() {
            private Button n;
            private Button y;
            private TextView title;
            private View inflate;

            @Override
            public void onItemClick(BaseQuickAdapter adapter, View view, final int position) {
                final PopupWindow window = new PopupWindow();
                window.setWidth(RecyclerView.LayoutParams.WRAP_CONTENT);
                window.setHeight(RecyclerView.LayoutParams.WRAP_CONTENT);
                window.setOutsideTouchable(true);
                window.setBackgroundDrawable(new ColorDrawable());
                inflate = View.inflate(MainActivity.this, R.layout.popu, null);
                title = inflate.findViewById(R.id.title);
                n = inflate.findViewById(R.id.n);
                y = inflate.findViewById(R.id.y);
                title.setText("是否添加数据库?");
                y.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        intent = new Intent(MainActivity.this, DBActivity.class);
                        intent.putExtra("key", myBeans.get(position));
                        startActivity(intent);
                    }
                });
                n.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        window.dismiss();
                    }
                });
                window.setContentView(inflate);
                window.showAsDropDown(view);
            }
        });
    }

    private void getMyBean(int i) {
        if (list != null) {
            if (list.get(i).getImages() != null) {
                images = list.get(i).getImages();
            } else {
                images = null;
            }
            myBeans.add(new MyBean(list.get(i).getUrl(), images, list.get(i).getCreatedAt(), list.get(i).getDesc()));
        }
    }
}

 

 

 

 

 

 

 

 

import android.support.annotation.Nullable;
import android.webkit.WebView;
import android.webkit.WebViewClient;

import com.chad.library.adapter.base.BaseQuickAdapter;
import com.chad.library.adapter.base.BaseViewHolder;
import com.recker.flybanner.FlyBanner;

import java.util.List;

import db.myrecy.R;
import db.myrecy.data.bean.MyBean;

/**
 * Created by Lenovo on 2018/06/04.
 */

public class MyAdapter extends BaseQuickAdapter {
    public MyAdapter(int layoutResId, @Nullable List data) {
        super(layoutResId, data);
    }

    @Override
    protected void convert(BaseViewHolder helper, MyBean item) {
            helper.setText(R.id.time,item.getTime());
            helper.setText(R.id.content,item.getContent());
            WebView webView= helper.getView(R.id.wvw);
           webView.getSettings().setJavaScriptEnabled(true);
           webView.loadUrl(item.getUrl());
           webView.setWebViewClient(new WebViewClient(){
               @Override
               public boolean shouldOverrideUrlLoading(WebView view, String url) {
                   view.loadUrl(url);
                   return true;
               }
           });
        FlyBanner fbnr= helper.getView(R.id.fbnr);
        if(item.getImgs()!=null){
            fbnr.setImagesUrl(item.getImgs());

            fbnr.startAutoPlay();
        }


    }
}

 

你可能感兴趣的:(优秀的RecyclerView框架加下拉刷新,上拉加载)