編輯:Android資訊
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則是用數據去填充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就是形成整個列表,只是依次填充類不同的數據而已。
前面已經准備好了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,大家有任何技術交流的問題都可以聯系我,批評也可以!另外,求工作!
Android ActionBar中Overflow Menu(溢出菜單)中的一些問題
前言 開始前我們先來關注一下Android Overflow menu的幾個相關問題: 什麼是Overflow menu Android 3.0以上默認不顯示o
傻瓜式Android APP開發入門教程
工作中有做過手機App項目,前端和android或ios程序員配合完成整個項目的開發,開發過程中與ios程序配合基本沒什麼問題,而android各種機子和rom的
Android自動化測試解決方案
桌面應用程序與浏覽器端的自動化測試都已經歷了十年的發展,無論是從工具上還是項目管理方 法論上都已經趨於成熟。而移動設備端應用程序的自動化測試近兩年才剛起步,似乎一
Android WebView 實現離線緩存閱讀
前言 本篇博客要實現的是一個離線下載和離線閱讀的功能,這是很多閱讀類app都常見的一個功能,典型的應用就是網易新聞。什麼是離線下載?其實這個概念是比較模糊,是離線