RecyclerView推出有一阵子了,随着5.0系统的安卓手机用户越来越多,ListView也逐渐被替代。
RecyclerView在性能上要比ListView更好,在滑动方面性能更优。功能代码耦合度低,并且提供了条目添加和删除动画。
使用方法:
一、在Activity的布局中添加RecyclerView:
<RelativeLayout 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"
>
<android.support.v7.widget.RecyclerView
android:id="@+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="8dp" />
</RelativeLayout>
因为Recycler是在v7包中,所以需要引入v7包。
1.Eclipse引入V7包的方法:打开SDK目录,并找到RecyclerView所在的文件夹:\sdk\extras\android\support\v7\recyclerview。导入到Eclipse中,设置该工程为Library。然后在我们的工程添加recyclerView的依赖即可。
2.AndroidStudio引入v7包的方法:
在app的build.gradle的dependencies最后添加一句:
compile ‘com.android.support:recyclerview-v7:24.0.1’
注意这里的v7包的版本要与SDK中Android Support Library版本一致。
二、设置Adapter
继承Adapter(这里继承的是RecyclerView.Adapter,不再是BaseAdapter),重写getItemCount、onBindViewHolder、onCreateViewHolder三个方法。
package com.example.recyclerview_demo;
import java.util.ArrayList;
import android.content.Context;
import android.support.v7.widget.RecyclerView.Adapter;
import android.support.v7.widget.RecyclerView.ViewHolder;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
//这里可以通过指定泛型来保证返回值为自定义的ViewHolder
public class RecyclerAdapter extends Adapter<RecyclerAdapter.MyViewHolder> {
private Context context;
private ArrayList<String> list;
// 构造方法传参
public RecyclerAdapter(Context context, ArrayList<String> list) {
super();
this.context = context;
this.list = list;
}
@Override
public int getItemCount() {
//条目数
return list.size();
}
//有新条目显示时调用 加载数据
@Override
public void onBindViewHolder(MyViewHolder holder, int position) {
Log.e("aa", "onBindViewHolder");
holder.tv.setText(list.get(position));}
//创建新的条目对象时调用
@Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int arg1) {
Log.e("aa", "onCreateViewHolder");
// 必须使用LayoutInflater,并且传入父布局,第三个参数指定为false
LayoutInflater inflater = LayoutInflater.from(context);
View itemView = inflater.inflate(R.layout.item_recyclerview, parent,false);
MyViewHolder holder = new MyViewHolder(itemView);
// 返回自定义Holder类对象
return holder;
}
// 自定义类继承ViewHolder
public class MyViewHolder extends ViewHolder {
public TextView tv;
/**
* @param itemView
* 每个item所需要的布局 只包含一个textView
*/
public MyViewHolder(View itemView) {
super(itemView);
tv = (TextView) itemView.findViewById(R.id.item_tv);
}
}
}
通过Log日志我们可以大致判断代码的调用特性:
RecyclerView首次加载:
滑动 RecyclerView 时 :
可以看到,首次创建时,需要加载要显示的条目组件,会调用onCreateViewHolder创建View。滑动时,由于条目组件已经创建好,直接复用就可以,所以不再重新Create。这就十分像我们写BaseAdapter中convertView的复用。
所以,这个Adapter实际上就是BaseAdapter和ViewHolder的封装。只需要自定义ViewHolder并设置每个条目中的内容即可,无需判断converView是否已经创建。并且可以指定泛型,直接返回自定义的ViewHolder。
在onCreateViewHolder()方法中,需要我们创建每个小条目的View对象。我之前喜欢用View.inflate方法,代码如下:
View itemView = View.inflate(context, R.layout.item_recyclerview, null);
MyViewHolder holder = new MyViewHolder(itemView);
使用这种方法会出现条目无法占满水平方向的问题。通过查看源码,发现View.inflate方法实际上就是调用LayoutInflater的inflate方法,在recyclerView中,必须指定父view并且infalte方法的第三个参数必须为false。我们使用
View.inflate(context, R.layout.item_recyclerview, null)
,虽然第三个参数为false,但是父view为null,所以就无法占满水平方向。但是如果使用
View.inflate(context, R.layout.item_recyclerview, parent)
,虽然传入了父布局,但是第三个参数会为true。系统会报错:child already has a parent。
使用LayoutInflater的inflate方法可以解决以上问题。
LayoutInflater inflater = LayoutInflater.from(context);
View itemView = inflater.inflate(R.layout.item_recyclerview, parent,false);
MyViewHolder holder = new MyViewHolder(itemView);
三、初始化RecyclerView
package com.example.recyclerview_demo;
import java.util.ArrayList;
import android.app.Activity;
import android.os.Bundle;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.RecyclerView.LayoutManager;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.RelativeLayout;
public class MainActivity extends Activity {
private RecyclerView mRecycler;
private ArrayList<String> data;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initData();
initView();
}
private void initView() {
mRecycler = (RecyclerView) this.findViewById(R.id.recycler_view);
//设置布局管理器
mRecycler.setLayoutManager(new LinearLayoutManager(this));
mRecycler.setAdapter(new RecyclerAdapter(this, data));
}
private void initData() {
data = new ArrayList<String>();
for (int i = 0; i < 50; i++) {
data.add(i + "");
}
}
}
与ListView一样,setAdapter就可以了。唯一需要多做的就是设置局管理器。