Android之ListView性能優化——使用ConvertView和ViewHolder


使用ConvertView和ViewHolder的優化是針對ListView的Adapter(BaseAdapter)的。這種優化的優點如下:
1)重用了ConveertView,在很大程度上減少了內存的消耗。通過判斷ConvertView是否為NULL,如果是NULL那么就需要生成一個新的View出來(通過LayoutInflater生成),綁定數據后顯示給用戶;如果ConvertView不是NULL,則我們需要做的就只有綁定數據並呈現給用戶。
2)由於ListView中的Item往往都是只有一個模板,即整個ListView的所有Item用的都是一套ID,所以我們可以把findViewById()方法提取出來,即全程之找一遍ID,這樣可以避免讓程序不停的做同樣的事情。這樣做的話通常需要用到另一個內部類(通常寫成ViewHolder,在這個類中定義Item中需要用到的控件的名稱),這樣做也可以方便我們調用控件的onClick()事件等等。
3)綜上,這樣做不僅減少了項目性能的消耗,也減少了內存的消耗。

 

下面貼代碼。先介紹一下這段代碼,這是筆者從一個“圖靈機器人”的程序中截取出來的一個BaseAdapter,其中的ChatMessage是聊天內容的實體類,其中有text(聊天的內容)、type(對方說話或者我方說話)等屬性。代碼如下:

 1 public class ChatListAdapter extends BaseAdapter {
 2     public static List<ChatMessage> chatList;
 3     private LayoutInflater inflater;
 4 
 5     public ChatListAdapter(Context context) {
 6         chatList = new ArrayList<ChatMessage>();
 7         inflater = LayoutInflater.from(context);
 8         chatList.add(new ChatMessage("您好,我是小慕,有什么可以幫您的嗎?", Type.ANSWER));
 9     }
10 
11     @Override
12     public int getCount() {
13         return chatList.size();
14     }
15 
16     @Override
17     public Object getItem(int position) {
18         return chatList.get(position);
19     }
20 
21     @Override // 返回某個位置的Item的類型(對面說話還是我方說話)
22     public int getItemViewType(int position) {
23         // Type是在ChatMessage中定義的枚舉類型的變量,有兩個枚舉值:ASK表示我向“小慕”提問,ANSWER表示“小慕”回答我
24         if (chatList.get(position).getType() == Type.ASK) {
25             return 0;
26         } else {
27             return 1;
28         }
29     }
30 
31     @Override // 返回ListView有幾種類型的Item
32     public int getViewTypeCount() {
33         return 2;
34     }
35 
36     @Override
37     public long getItemId(int position) {
38         return position;
39     }
40 
41     @Override // 布局Item
42     public View getView(int position, View convertView, ViewGroup parent) {
43         ViewHolder holder;
44         if (convertView == null) { // 如果為空,就表示是第一次加載,還沒有加入到緩存中
45             holder = new ViewHolder();
46             if (getItemViewType(position) == 0) { // 我方說話
47                 convertView = inflater.inflate(R.layout.sideworks_chatlist_item_ask, null);
48                 holder.time = (TextView) convertView.findViewById(R.id.control_chatitem_ask_time);
49                 holder.info = (TextView) convertView.findViewById(R.id.control_askitem_message);
50             } else if (getItemViewType(position) == 1) { // 對方說話
51                 convertView = inflater.inflate(R.layout.sideworks_chatlist_item_reply, null);
52                 holder.time = (TextView) convertView.findViewById(R.id.control_chatitem_reply_time);
53                 holder.info = (TextView) convertView.findViewById(R.id.control_replyitem_message);
54             }
55             convertView.setTag(holder); // 加入緩存
56         } else {
57             holder = (ViewHolder) convertView.getTag(); // 如果ConvertView不為空,則表示在緩存中
58         }
59         holder.time.setText(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
60         holder.info.setText(chatList.get(position).getText());
61         return convertView;
62     }
63 
64     // 自定義的容器類(相當於一個Item),其中放置着需要我們放置數據的控件的名稱
65     private static class ViewHolder {
66         TextView time;
67         TextView info;
68     }
69 }

 

最后說一下,當我們說了話或者對方說了話,我們就需要更新視圖,方法是:先在chatList中添加一條數據,然后調用BaseAdapter(注意一定要是同一個Adapter實例)的notifyDataSetChanged()方法進行刷新。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM