吐槽:一直想寫一篇完整的,能系統地介紹某個知識點的文章,但由于技術不夠加上懶,只能仰望其他大神寫出的非常優秀的文章,從中學習一二。今天看了hongyang大神寫的關于recycleview的博客,獲益良多啊!不過鴻神可能要全面解析這個控件,沒那么多篇幅來寫一些原理問題,所以我google了一番結合listview來介紹他們的優化原理(作為初學者,我僅憑自己理解去寫這篇文章,如有錯誤,你來打我啊(開玩笑...),還是非常希望各位能及時幫我更正)
首先我們來看下,沒有優化過的listview中getView方法(因為是介紹原理問題,所有的代碼就不貼上了,百度一大堆)
@Override
public View getView(int position, View convertView, ViewGroup parent) {
//listview_item里只有一個textview
View view = View.inflate(MainActivity.this, R.layout.listview_item,
null);
//使用每一次都findviewById的方法來獲得listview_item內部的組件
TextView tv_item = (TextView) view.findViewById(R.id.tv_item);
tv_item.setText(list.get(position));
return view;
}
當我們的item有十幾個的時候,手機屏幕不足以完全顯示(說iphone18的走開!!),所以我們要向上滑動以顯示下面其他的item,但這時前面的item就會淡出屏幕,再向下滑動,又顯示前面的item了,但你會發現,無論顯示第一個item還是顯示最后一個item,只要出現在屏幕上一次,就會調用一次getView來創建這個item。這無疑是很浪費內存的,所以就有下面的優化方案。
public View getView(int position, View convertView, ViewGroup parent) {
View view;
ViewHolder holder;
// 判斷convertView的狀態,來達到復用效果
if (null == convertView) {
// 如果convertView為空,則表示第一次顯示該條目,需要創建一個view
view = View.inflate(MainActivity.this, R.layout.listview_item,
null);
//新建一個viewholder對象
holder = new ViewHolder();
//將findviewbyID的結果賦值給holder對應的成員變量
holder.tvHolder = (TextView) view.findViewById(R.id.tv_item);
// 將holder與view進行綁定
view.setTag(holder);
} else {
// 否則表示可以復用convertView
view = convertView;
holder = (ViewHolder) view.getTag();
}
// 直接操作holder中的成員變量即可,不需要每次都findViewById
holder.tvHolder.setText(list.get(position));
return view;
}
convertView這個參數設計非常巧妙,是用來儲存那些被你萬惡的手指滑動導致淡出的item,當它為空,說明之前沒有被創建過,所以就創建這個item,它不為空時,嘿嘿,說明是被淡出的item,之前有被創建,那就直接拿出來用就行啦。關于ViewHolder很多資料也有介紹,這里也不再贅述了。來看下圖更有利于理解:
上面是ListView的。接下來我們來看下RecycleView:
package com.example.q_recycler;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.LinearLayout;
import android.widget.TextView;
import java.util.List;
/**
* Created by 強強 on 2017/2/6.
*/
public class MyRecycleviewAdapter extends RecyclerView.Adapter<MyRecycleviewAdapter.ViewHolder>{
List<String> list;
public MyRecycleviewAdapter(List<String> list){
this.list=list;
}
@Override
public MyRecycleviewAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view= LayoutInflater.from(parent.getContext()).inflate(R.layout.id_num,parent,false);
return new ViewHolder(view);
}
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
holder.tv.setText(list.get(position));
}
@Override
public int getItemCount() {
if(list!=null) return list.size();
else
return 0;
}
class ViewHolder extends RecyclerView.ViewHolder {
public TextView tv;
public ViewHolder(View itemView) {
super(itemView);
tv= (TextView) itemView.findViewById(R.id.id_num);
}
}
}
RecycleView作為ListView的升級版,自然有它的優勢,拋棄那n多的功能(被鴻神稱為藝術般的控件),它的內存優化也是獨到的哦。
我的理解是:RecycleView提供了一個緩存機制,當一個item沒有被創建時,就會調用onCreateViewHolder的方法創建這個item,同時也放入到緩存中,以ViewHolder的形式返回,當要顯示item時,就會在緩存中尋找有沒有創建過這個item,如果創建了的話就直接調用onBindViewHolder方法進行渲染顯示。這里也避免重復創建item了,可見,它們的優化原理是相差無幾的,結合起來更能讓人理解。
結束語:這又是一片簡文(好符合簡書哦),文中只介紹了我對于這兩個控件的一點點見解(個人理解),不敢肯定百分百是對的。還有,文中還有很多東西沒有介紹到,因為我認為很多大神都對它們有非常詳細的博客(懶),隨便一搜就可以看到了,我再寫的話,,,會很累的!!!!哈哈,下面貼兩個詳解博客吧
http://blog.csdn.net/skykingf/article/details/50827141