RecyclerView與ListView原理是類似的:都是僅僅維護少量的View并且可以展示大量的數據集。RecyclerView用以下兩種方式簡化了數據的展示和處理:
使用LayoutManager來確定每一個item的排列方式。 為增加和刪除項目提供默認的動畫效果。 你也可以定義你自己的LayoutManager和添加刪除動畫,RecyclerView項目結構如下:
Adapter:使用RecyclerView之前,你需要一個繼承自RecyclerView.Adapter的適配器,作用是將數據與每一個item的界面進行綁定。 LayoutManager:用來確定每一個item如何進行排列擺放,何時展示和隱藏?;厥栈蛑赜靡粋€View的時候,LayoutManager會向適配器請求新的數據來替換舊的數據,這種機制避免了創建過多的View和頻繁的調用findViewById方法(與ListView原理類似)。
目前SDK中提供了三種自帶的LayoutManager:
LinearLayoutManager GridLayoutManager StaggeredGridLayoutManager
recyclerView = (RecyclerView) findViewById(R.id.recyclerView); LinearLayoutManager layoutManager = new LinearLayoutManager(this ); //設置布局管理器 recyclerView.setLayoutManager(layoutManager); //設置為垂直布局,這也是默認的 layoutManager.setOrientation(OrientationHelper. VERTICAL); //設置Adapter recyclerView.setAdapter( recycleAdapter); //設置分隔線 recyclerView.addItemDecoration( new DividerGridItemDecoration(this )); //設置增加或刪除條目的動畫 recyclerView.setItemAnimator( new DefaultItemAnimator());①onCreateViewHolder() 這個方法主要生成為每個Item inflater出一個View,但是該方法返回的是一個ViewHolder。該方法把View直接封裝在ViewHolder中,然后我們面向的是ViewHolder這個實例,當然這個ViewHolder需要我們自己去編寫。直接省去了當初的convertView.setTag(holder)和convertView.getTag()這些繁瑣的步驟。
②onBindViewHolder() 這個方法主要用于適配渲染數據到View中。方法提供給你了一個viewHolder,而不是原來的convertView。
③getItemCount() 這個方法就類似于BaseAdapter的getCount方法了,即總共有多少個條目。
高級控件使用講解的參考博客
參考博客,點擊查看
1、添加依賴
compile 'com.android.support:recyclerview-v7:24.2.1'2. 使用RecyclerView
<android.support.v7.widget.RecyclerView android:id="@+id/rv" android:layout_width="match_parent" android:layout_height="match_parent" />3.創建適配器設置給RecyclerView
View view = inflater.inflate(R.layout.fragment_home, container, false); //獲取rv控件 RecyclerView rv = (RecyclerView) view.findViewById(R.id.rv); rv.setLayoutManager(new LinearLayoutManager(getContext())); //設置Adapter MyAdapter adapter = new MyAdapter(); rv.setAdapter(adapter); return view;4.創建適配器
PRivate class MyAdapter extends RecyclerView.Adapter<MyHolder>{ private final List<String> list; public MyAdapter(){ list = new ArrayList<String>(); for (int i = 0; i < 30; i++) { list.add("商品記錄" + i)}} //OnCreateViewHolder用來給rv創建緩存的 public MyHolder onCreateViewHolder(ViewGroup parent, int viewType) { //參數3:判斷條件 true 1.是打氣 2.添加到parent View view = LayoutInflater.from(getContext()).inflate(R.layout.main_recyclerview_item,parent,false); MyHolder holder = new MyHolder(view); return holder; } //給緩存控件設置數據 public void onBindViewHolder(MyHolder holder, int position) { String item = list.get(position); holder.textView.setText(item); holder.icon.setImageResource(R.drawable.ic_default); } //獲取記錄數 public int getItemCount() { return list.size(); }5.創建HolderView
public class MyHolder extends RecyclerView.ViewHolder { public ImageView icon; public TextView textView; //實現的方法 public MyHolder(View itemView) { super(itemView); icon= (ImageView) itemView.findViewById(R.id.item_iv_icon); textView= (TextView) itemView.findViewById(R.id.item_tv_title); }}思路:不寫死空間變量,而采用Map方式。 步驟:先關注比較火的控件庫 使用一下,看一下好處 學習下底層源代碼 自己動手體會 ①封裝了BaseHolder
//抽取BaseHolder繼承RecyclerView.ViewHolderpublic class BaseHolder extends RecyclerView.ViewHolder { //不寫死控件變量,而采用Map方式 private HashMap<Integer, View> mViews = new HashMap<>(); public BaseHolder(View itemView) { super(itemView); } /** *獲取控件的方法 */ public<T> T getView(Integer viewId){ //根據保存變量的類型 強轉為該類型 View view = mViews.get(viewId); if(view==null){ view= itemView.findViewById(viewId); //緩存 mViews.put(viewId,view); } return (T)view; } /** *傳入文本控件id和設置的文本值,設置文本 */ public BaseHolder setText(Integer viewId, String value){ TextView textView = getView(viewId); if (textView != null) { textView.setText(value); } return this; } /** * 傳入圖片控件id和資源id,設置圖片 */ public BaseHolder setImageResource(Integer viewId, Integer resId) { ImageView imageView = getView(viewId); if (imageView != null) { imageView.setImageResource(resId); } return this; } //...還可以擴展出各種控件。 //Fluent API 鏈式api obj.setxxx().setyyy()....}②Holder封裝好之后,再封裝BaseAdapter
封裝的時候,部分參數可以選擇由外部的構造函數或者set方法 public class BaseAdapter<T> extends RecyclerView.Adapter<BaseHolder> { private List<T> mList = new ArrayList<>(); private int layoutId; public BaseAdapter(int layoutId,List<T> list){ this.layoutId=layoutId; this. mList=list; } //onCreateViewHolder用來給rv創建緩存 @Override public BaseHolder onCreateViewHolder(ViewGroup parent, int viewType) { //參數3 判斷條件 true 1.打氣 2.添加到paraent // false 1.打氣 (參考parent的寬度) View view = LayoutInflater.from(parent.getContext()).inflate(layoutId, parent, false); BaseHolder holder = new BaseHolder(view); return holder; } //onBindViewHolder給緩存控件設置數據 @Override public void onBindViewHolder(BaseHolder holder, int position) { T item = mList.get(position); convert(holder,item); } protected void convert(BaseHolder holder, T item) { //什么都沒有做 } //獲取記錄數據 @Override public int getItemCount() { return mList.size(); } }③封裝之后,繼承實現
/** *1.extends 把父類的代碼繼承過來。 可以少寫很多代碼。 *2.因為是全部拿來的代碼,所以不是所有的代碼都適合當前。對于不適合當前的代碼(方法) * 我們可選擇@Override 覆蓋|重寫 */public class MyHomeAdapter extends BaseAdapter<String> { public MyHomeAdapter(List<String> list) { super(R.layout.main_recyclerview_item, list); } @Override protected void convert(BaseHolder holder, String item) { holder.setText(R.id.item_tv_title,item).setImageResource(R.id.image,R.drawable.ic_default); }}④封裝之后,代碼實現
public class HomeFragment extends Fragment { private List<String> list; @Override public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { View view = inflater.inflate(R.layout.fragment_home, container, false); //獲取rv控件 RecyclerView rv = (RecyclerView) view.findViewById(R.id.rv); b rv.setLayoutManager(new LinearLayoutManager(getContext())); initData(); //設置Adapter MyHomeAdapter adapter = new MyHomeAdapter(list); rv.setAdapter(adapter); return view;依賴 布局文件activity_recycler_view.xml:
<?xml version="1.0" encoding="utf-8"?><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/id_recyclerview" android:divider="#FFB900" android:dividerHeight="1dp" android:layout_width="match_parent" android:layout_height="match_parent"/></RelativeLayout>讓我們來看看變化最大的Adaper:
class HomeAdapter extends RecyclerView.Adapter<HomeAdapter.MyViewHolder>{ private List<String> mList; private Context mContext;; public HomeAdapter(Context mContext,List<String>mList){ this.mContext=mContext; this.mList=mList; } public void removeData(int position) { mList.remove(position); notifyItemRemoved(position); } @Override public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { MyViewHolder holder = new MyViewHolder(LayoutInflater.from( mContext).inflate(R.layout.item_recycler, parent, false)); return holder; } @Override public void onBindViewHolder(final MyViewHolder holder, final int position) { holder.tv.setText(mList.get(position)); } @Override public int getItemCount() { return mList.size(); } class MyViewHolder extends RecyclerView.ViewHolder { TextView tv; public MyViewHolder(View view) { super(view); tv = (TextView) view.findViewById(R.id.tv_item); } }}最大的改進就是對ViewHolder進行了封裝定義,不用自己去自定義了,另外Adaper繼承RecyclerView.Adapter,在onCreateViewHolder加載條目布局,在onBindViewHolder中將視圖與數據進行綁定。 布局文件item_recycler.xml:
<?xml version="1.0" encoding="utf-8"?><FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:background="@android:color/white" android:layout_height="wrap_content" > <TextView android:id="@+id/tv_item" android:layout_width="match_parent" android:layout_height="50dp" android:gravity="center" android:text="moon" /></FrameLayout>高級進階—分割線
新聞熱點
疑難解答