第一次写博客,表达可能不是很好,也是仅供初学的朋友们参考下,希望大家见谅。
Recyclerview是 Listview 的升级版本,在项目中使用较为广泛,官方也推荐我们使用 Recyclerview 来代替 Listview,在此就不多说 Recyclerview 的优势特点 balala了。。。
在实际项目中,列表通常是分页的,请求服务器也只会一次请求若干条,按需加载,这样比较节省流量,这样就有了我们很常见的下拉加载更多的功能,具体的实现效果如下图:
该activity的布局文件:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.geek.loadmoredemo.MainActivity">
<android.support.v7.widget.RecyclerView
android:id="@+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</LinearLayout>
底部加载更多的view:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:orientation="horizontal"
android:padding="@dimen/activity_vertical_margin">
<ProgressBar
style="@android:style/Widget.Holo.ProgressBar.Small"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="8dp"
android:text="正在加载..."/>
</LinearLayout>
数据item的view:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
xmlns:tools="http://schemas.android.com/tools"
android:padding="@dimen/activity_vertical_margin"
android:orientation="horizontal">
<ImageView
android:src="@mipmap/ic_launcher"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<LinearLayout
android:gravity="center"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:id="@+id/title"
android:gravity="center"
tools:text="我是标题"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<TextView
android:id="@+id/content"
android:gravity="center"
tools:text="我是内容"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</LinearLayout>
</LinearLayout>
这里每次会加载10条数据,当列表滑动到最后一个已加载完成的item 时会出现加载更多的view并加载下10条数据。
在此都假设你已经熟悉了 Recylerview 的基本使用方法,分页的操作主要是在该 recyclerview 的 adapter 中实现的,代码如下:
package com.geek.loadmoredemo;
import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import java.util.ArrayList;
import java.util.List;
import butterknife.Bind;
import butterknife.ButterKnife;
public class DemoAdapter extends RecyclerView.Adapter {
private List<Demo> mDemos = new ArrayList<>();
private Context mContext;
private LayoutInflater mLayoutInflater;
private ILoadCallback mCallback;
public DemoAdapter(Context context, List<Demo> list) {
mContext = context;
mLayoutInflater = LayoutInflater.from(context);
addData(list);
}
//对外暴露设置接口方法
public void setLoadCallback(ILoadCallback callback) {
this.mCallback = callback;
}
public void addData(List<Demo> list) {
mDemos.addAll(list);
notifyDataSetChanged();//添加数据后通知 adpter 更新
}
@Override
public int getItemViewType(int position) {
if (position == mDemos.size()) {
return R.layout.load_more_layout;
} else {
return R.layout.demo_item_layout;
}
}
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = mLayoutInflater.inflate(viewType, parent, false);
if (viewType == R.layout.load_more_layout) {
return new LoadMoreVH(view);
} else {
return new DemoVH(view);
}
}
@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
if (holder instanceof DemoVH) {
((DemoVH) holder).bind(mDemos, position);
} else if (holder instanceof LoadMoreVH) {
Log.d("loadmore", "loading...");
mCallback.onLoad();
}
}
@Override
public int getItemCount() {
return mDemos.size()+1;//recylerview的item的总数目是所有数据数量加一
}
//普通item的viewholder
static class DemoVH extends RecyclerView.ViewHolder {
@Bind(R.id.title)
public TextView mTitle;
@Bind(R.id.content)
public TextView mContent;
public DemoVH(View itemView) {
super(itemView);
ButterKnife.bind(this, itemView);
}
public void bind(List<Demo> demo, int position) {
mTitle.setText(demo.get(position).title);
mContent.setText(demo.get(position).content);
}
}
//底部加载更多item的viewholder
static class LoadMoreVH extends RecyclerView.ViewHolder {
public LoadMoreVH(View itemView) {
super(itemView);
}
}
//回调接口,用于回调加载数据的方法
interface ILoadCallback {
void onLoad();
}
}
- 首先创建两个 ViewHolder类,继承RecyclerView.ViewHolder(使用 static 关键字修饰内部类就不会持有外部类的强引用,这样不会造成内存泄露问题),一个是需要展示的 item 的,一个是加载更多的 view 的。
- 然后重写 getItemType(int position)方法,判断如果position 是数据集合的最后一个,就返回加载更多的 view 的布局文件资源 ID,否则返回数据 item 的。
- 重写onCreateViewHolder(ViewGroup parent, int viewType)方法,在此方法中判断 viewType 不同,返回不同的 viewholder,这样就在 recylerview 创建 item 的时候会根据不同的 item 位置显示数据或者加载更多了。
- 重写onBindViewHolder(RecyclerView.ViewHolder holder, int position)方法,利用 instanceof 关键字判断 holder 对象是哪个的实例,如果是数据 item 的就执行绑定数据的操作;如果是加载更多 view 的就执行回调接口中的 onLoad()方法,将数据加载的具体逻辑交给外部处理。
该 Acitivity 代码如下:
package com.geek.loadmoredemo;
import android.os.Bundle;
import android.os.Handler;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import java.util.ArrayList;
import java.util.List;
public class MainActivity extends AppCompatActivity {
RecyclerView mRecyclerView;
private List<Demo> mDemos = new ArrayList<>();
private DemoAdapter mAdapter;
private Handler mHandler = new Handler();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
intiData();
initView();
}
private void intiData() {
//首次加载数据
for (int i = 0; i < 10; i++) {
mDemos.add(new Demo("我是标题" + i, "我是内容" + i));
}
}
private void initView() {
mRecyclerView = (RecyclerView) findViewById(R.id.recycler_view);
mAdapter = new DemoAdapter(this, mDemos);
mAdapter.setLoadCallback(new DemoAdapter.ILoadCallback() {
@Override
public void onLoad() {
mHandler.postDelayed(new Runnable() {//延时处理,模拟网络操作
@Override
public void run() {
List<Demo> demos = new ArrayList<Demo>();
for (int i = mDemos.size(); i < mDemos.size()+10; i++) {//每次请求10条数据
demos.add(new Demo("我是标题" + i, "我是内容" + i));
}
mAdapter.addData(demos);
mDemos.addAll(demos);
}
}, 2000);
}
});//设置接口,实现加载数据的回调方法
mRecyclerView.setAdapter(mAdapter);
mRecyclerView.addItemDecoration(new DividerItemDecoration(this, DividerItemDecoration.VERTICAL_LIST));
mRecyclerView.setLayoutManager(new LinearLayoutManager(this));
}
}
这样就完整实现了 Recylerview 的加载更多功能,总体来说还是很简单的,如果还是有不明白的,可能你对 Recylerview 的使用方法还不够了解,可以自行学习。