當資料來源是cursor,顯示界面為ListView就可以很方便的使用CursorAdapter
extends CursorAdapter的時候需要override bindView()以及newView()
bindView會在顯示每一個item的時候被呼叫
newView則會在需要的時候被呼叫,譬如說第一次建立此位置的View時,或是此位置的View已經被回收時
@Override
public void bindView(View view, Context context, Cursor cursor) {
if (view == null || cursor == null)
return;
String bucketName = null, displayName = null;
...
}
@Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
LayoutInflater inflater = (LayoutInflater) this.context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
return inflater.inflate(R.layout.media_item, null);
}
如果總共有100個item,銀幕上最多顯示8個item
那畫面顯示出來時newView()/bindView()就會分別被呼叫8次,滑動時就只會呼叫bindView(),偶而才會呼叫newView()
一般如果是直接使用BaseAdapter,會override getView()這個method
通常寫法會是判斷傳入的view是不是null,null則inflate一個新的view,非null則直接拿來用
CursorAdapter也是extends自BaseAdapter所以也會有getView()這個method
網路上查到的資料是CursorAdapter裡getView()的實作就是判斷是否需要建立view,需要則呼叫newView(),不需要則直接呼叫bindView()
由於最近在做performance tuning,所以也看到一個ViewHolder的用法,主要是減少findViewById()運算
class ViewHolder {
TextView text1;
TextView text2;
}
@Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
LayoutInflater inflater = (LayoutInflater) this.context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View view = inflater.inflate(R.layout.media_item, null);
ViewHolder vh = new ViewHolder();
vh.text1 = (TextView) view.findViewById(R.id.textView1);
vh.text2 = (TextView) view.findViewById(R.id.textView2);
view.setTag(vh);
return view;
}
@Override
public void bindView(View view, Context context, Cursor cursor) {
if (view == null || cursor == null)
return;
String bucketName = null, displayName = null;
bucketName = cursor.getString(2);
displayName = cursor.getString(3);
ViewHolder vh = (ViewHolder) view.getTag();
vh.text1.setText(bucketName);
vh.text2.setText(displayName);
}
View有一個setTag(Object)的method,newView()的時候,先將之後會用到的view reference都存在ViewHolder,再set到inflate出的view中
bindView()的時候就不需要再執行findViewById,直接getTag()就可以將各個view的reference取出來用
當資料數量很多的時候,透過這種寫法應該能提升不少performance
這次tuning performance也發生了一個小插曲
當我把程式改完,理論上會比原本方法好很多,但結果卻發現,比原本的方式速度還慢
找了好久,程式比了又比,這邊mark完比那邊,最後終於發現root cause
程式是要將cursor中的資料轉換成local的list,裡面有一個欄位為date,在database中是一串數字
get出來透過下面的方式轉成字串存在local list中
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd HH:mm:ss", Locale.US);
String date = dateFormat.format(new Date(databaseDate));
databaseDate為datebase中的數字
由於我測試的資料有2000多筆,所以這樣的轉換作了2000多次
本來理想狀況改完之後的速度應該比原先的快,結果竟然慢了2/3倍
表示SimpleDateFormat的轉換實際上還蠻耗時的
後來改成直接在local list存數字,當需要顯示date字串時在進行轉換,速度跟飛的一樣!!!
以後進行performance tuning時要注意這些被忽略的小地方阿!!!
Nice findings! Thanks!
回覆刪除