RecyclerView是传统ListView的一个很好的替代,具有很好的拓展性,初次接触RecyclerView可能会被其复杂的逻辑搞晕,本文就以一个简单的实例带小伙伴们理清其中的关系。
一 添加依赖包
本文所使用的IDE为AndroidStudio。
依次点击File--->Project Structure--->左下角Module的app--->Dependencis--->点击左下方的+号,选择recycler view即可。
二 准备工作
首先创建一个名为NotesListFragment的fragment,对应的布局文件名为fragment_notes_list。接着将该fragment加入到主Activity中(关于如何在Activity中操作fragment将另作文章说明,此处省略啦),接下来在NotesListFragment中定义一个私有字段
private RecyclerView noteRecycler;
我们将要实现的是一个显示笔记的RecyclerView,这里将笔记类定义如下:
package com.aristark.note;
import java.util.Date;
import java.util.UUID;
public class Note {
private UUID uuid;
private String title;
private String content;
private Date date;
private String tag;
public Note{
uuid = UUID.randomUUID();
date = new Date();
}
public UUID getUuid() {
return uuid;
}
public Date getDate() {
return date;
}
public void setTitle(String title) {
this.title = title;
}
public String getTitle() {
return title;
}
public void setContent(String content) {
this.content = content;
}
public String getContent() {
return content;
}
public void setTag(String tag) {
this.tag = tag;
}
public String getTag() {
return tag;
}
}
为了操作方便,我们再创建一个NoteLab类:
package com.aristark.note;
import android.content.Context;
import java.util.ArrayList;
public class NoteLab {
private static NoteLab sNoteLab; //for the global use
private ArrayList<Note> notes;
private NoteLab(Context context){
notes = new ArrayList<Note>();
//generate 100 Note Objects
for (int i=0;i<100;i++){
Note note = new Note();
note.setTitle("this is title "+i);
note.setContent("this is content"+i+"balabalabalabalalabalabalabalabalala\nbalabalabalabalalabalabalabala balala\nbalabalabalabalalabalabalabalabalala\nbalabalabalabalalabalabalab alabalala\nbalabalabalabalalabalabalabalabalala\n");
notes.add(note);
}
}
public static NoteLab getNoteLab(Context context){
if (sNoteLab == null){
sNoteLab = new NoteLab(context);
}
return sNoteLab;
}
public ArrayList<Note> getNotes() {
return notes;
}
}
注意体会该类所使用的单例模式,sNoteLab以静态方式存在,既节省了内存,又可以让应用的各个部件方便的访问。在构造方法NoteLab中,我们生成100个Note对象以作后面的测试。
三 ViewHolder和Adapter
这两个类是实现列表的关键,其实从字面含义很容易猜测这两个类的作用,ViewHolder操作的是列表每个部分的布局,而Adapter则是用数据去填充View,虽然解释的不是很准确,但姑且这么理解是没问题的。那么下面我们就在NotesListFragment里创建这两个类:
1 首先创建NoteHolder
private class NoteHolder extends RecyclerView.ViewHolder{
public NoteHolder(View root) {
super(root);
}
}
这个类很简单,值得注意的是自动创建的构造方法所传入的参数名叫itemView,这里我将其改为root,因为接下来我们通过这个构造方法传进来的是一个完整的布局文件,而不仅仅是一个控件。
2 创建Adapter
private class NoteAdapter extends RecyclerView.Adapter<NoteHolder>{
private List<Note> notes;
public NoteAdapter(List<Note> notes){
this.notes = notes;
}
public void setNotes(List<Note> notes) {
this.notes = notes;
}
@Override
public NoteHolder onCreateViewHolder(ViewGroup parent, int viewType) {
return null;
}
@Override
public void onBindViewHolder(NoteHolder holder, int position) {
}
@Override
public int getItemCount() {
return 0;
}
}
前面说了Adapter是有关于数据的操作了,因此在类的内部定义notes字段也很容易理解,我们再来看看这里覆写的三个方法,onCreateViewHolder返回值是NoteHolder,因此它是用来创建ViewHolder,onBindViewHolder则可以直接操作NoteHolder,position指的是当前View处在整个List的位置(我们的目的是要创建类似于微信消息列表的一个列表,其每个部件的布局其实是一样的,只是填充的数据不一样而已),以便按照当前的位置填入相应的数据。getItemCount则是返回需要相应布局的总数。talk is cheap,show me the code。说再多恐怕也难以表达,下面看代码,多看几遍,自然而然就会用了。
private class NoteAdapter extends RecyclerView.Adapter<NoteHolder>{
private List<Note> notes;
public NoteAdapter(List<Note> notes){
this.notes = notes;
}
public void setNotes(List<Note> notes) {
this.notes = notes;
}
@Override
public NoteHolder onCreateViewHolder(ViewGroup parent, int viewType) {
LayoutInflater layoutInflater = LayoutInflater.from(getActivity());
View view = layoutInflater.inflate(R.layout.list_item_note,parent,false);
return new NoteHolder(view);
}
@Override
public void onBindViewHolder(NoteHolder holder, int position) {
Note note = notes.get(position);
holder.bindView(note);
}
@Override
public int getItemCount() {
return notes.size();
}
}
其中R.layout.list_item_note的布局文件如下:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/list_item_note_title" />
</LinearLayout>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/list_item_note_content" />
</LinearLayout>
这里只简单的使用了Note类中title和content两个字段,其实就是这个view就是形成整个列表,只是依次填充类不同的数据而已。
四 RecyclerView的使用
前面已经准备好了ViewHolder和Adapter,接下来要做的就是将这些部件组装在一起,最后将整个fragment贴出来,大家注意onCreateView里是 Ruhr操作的!
public class NotesListFragment extends Fragment {
private RecyclerView noteRecycler;
private NoteAdapter noteAdapter;
public NotesListFragment() {
// Required empty public constructor
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
//return inflater.inflate(R.layout.fragment_notes_list, container, false);
View root = inflater.inflate(R.layout.fragment_notes_list,container,false);
noteRecycler = (RecyclerView) root.findViewById(R.id.note_recycler_view);
noteRecycler.setLayoutManager(new LinearLayoutManager(getActivity()));
NoteLab noteLab = NoteLab.getNoteLab(getActivity());
ArrayList<Note> notes = noteLab.getNotes();
noteAdapter = new NoteAdapter(notes);
noteRecycler.setAdapter(noteAdapter);
return root;
}
private class NoteHolder extends RecyclerView.ViewHolder{
private TextView noteTitle;
private TextView noteContent;
public NoteHolder(View root) {
super(root);
noteTitle = (TextView) root.findViewById(R.id.list_item_note_title);
noteContent = (TextView) root.findViewById(R.id.list_item_note_content);
}
public void bindView(Note note){
noteTitle.setText(note.getTitle());
noteContent.setText(note.getContent());
}
}
private class NoteAdapter extends RecyclerView.Adapter<NoteHolder>{
private List<Note> notes;
public NoteAdapter(List<Note> notes){
this.notes = notes;
}
public void setNotes(List<Note> notes) {
this.notes = notes;
}
@Override
public NoteHolder onCreateViewHolder(ViewGroup parent, int viewType) {
LayoutInflater layoutInflater = LayoutInflater.from(getActivity());
View view = layoutInflater.inflate(R.layout.list_item_note,parent,false);
return new NoteHolder(view);
}
@Override
public void onBindViewHolder(NoteHolder holder, int position) {
Note note = notes.get(position);
holder.bindView(note);
}
@Override
public int getItemCount() {
return notes.size();
}
}
}
后记
最后给大家贴出最后的效果图吧!
这是我第一次写博客,解释的不多,代码较多,一来是因为我没有很多表达的经验,二来我觉得很多时候类名,函数名足以说明它的用途,过多解释怕会误导大家。whatever,还是希望得到大家的支持,我会在坚持写代码的同时也坚持把博客写下去,是对自己学到的知识的总结,也希望确确实实可以帮到需要帮助的朋友。我的QQ891871898,大家有任何技术交流的问题都可以联系我,批评也可以!另外,求工作!
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。