1 /*
2  * Copyright (C) 2008 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.example.android.apis.view;
18 
19 import android.app.ListActivity;
20 import android.content.Context;
21 import android.os.Bundle;
22 import android.view.LayoutInflater;
23 import android.view.View;
24 import android.view.ViewGroup;
25 import android.widget.BaseAdapter;
26 import android.widget.TextView;
27 import android.widget.ImageView;
28 import android.graphics.BitmapFactory;
29 import android.graphics.Bitmap;
30 import com.example.android.apis.R;
31 
32 /**
33  * Demonstrates how to write an efficient list adapter. The adapter used in this example binds
34  * to an ImageView and to a TextView for each row in the list.
35  *
36  * To work efficiently the adapter implemented here uses two techniques:
37  * - It reuses the convertView passed to getView() to avoid inflating View when it is not necessary
38  * - It uses the ViewHolder pattern to avoid calling findViewById() when it is not necessary
39  *
40  * The ViewHolder pattern consists in storing a data structure in the tag of the view returned by
41  * getView(). This data structures contains references to the views we want to bind data to, thus
42  * avoiding calls to findViewById() every time getView() is invoked.
43  */
44 public class List14 extends ListActivity {
45 
46     private static class EfficientAdapter extends BaseAdapter {
47         private LayoutInflater mInflater;
48         private Bitmap mIcon1;
49         private Bitmap mIcon2;
50 
EfficientAdapter(Context context)51         public EfficientAdapter(Context context) {
52             // Cache the LayoutInflate to avoid asking for a new one each time.
53             mInflater = LayoutInflater.from(context);
54 
55             // Icons bound to the rows.
56             mIcon1 = BitmapFactory.decodeResource(context.getResources(), R.drawable.icon48x48_1);
57             mIcon2 = BitmapFactory.decodeResource(context.getResources(), R.drawable.icon48x48_2);
58         }
59 
60         /**
61          * The number of items in the list is determined by the number of speeches
62          * in our array.
63          *
64          * @see android.widget.ListAdapter#getCount()
65          */
getCount()66         public int getCount() {
67             return DATA.length;
68         }
69 
70         /**
71          * Since the data comes from an array, just returning the index is
72          * sufficent to get at the data. If we were using a more complex data
73          * structure, we would return whatever object represents one row in the
74          * list.
75          *
76          * @see android.widget.ListAdapter#getItem(int)
77          */
getItem(int position)78         public Object getItem(int position) {
79             return position;
80         }
81 
82         /**
83          * Use the array index as a unique id.
84          *
85          * @see android.widget.ListAdapter#getItemId(int)
86          */
getItemId(int position)87         public long getItemId(int position) {
88             return position;
89         }
90 
91         /**
92          * Make a view to hold each row.
93          *
94          * @see android.widget.ListAdapter#getView(int, android.view.View,
95          *      android.view.ViewGroup)
96          */
getView(int position, View convertView, ViewGroup parent)97         public View getView(int position, View convertView, ViewGroup parent) {
98             // A ViewHolder keeps references to children views to avoid unneccessary calls
99             // to findViewById() on each row.
100             ViewHolder holder;
101 
102             // When convertView is not null, we can reuse it directly, there is no need
103             // to reinflate it. We only inflate a new View when the convertView supplied
104             // by ListView is null.
105             if (convertView == null) {
106                 convertView = mInflater.inflate(R.layout.list_item_icon_text, null);
107 
108                 // Creates a ViewHolder and store references to the two children views
109                 // we want to bind data to.
110                 holder = new ViewHolder();
111                 holder.text = (TextView) convertView.findViewById(R.id.text);
112                 holder.icon = (ImageView) convertView.findViewById(R.id.icon);
113 
114                 convertView.setTag(holder);
115             } else {
116                 // Get the ViewHolder back to get fast access to the TextView
117                 // and the ImageView.
118                 holder = (ViewHolder) convertView.getTag();
119             }
120 
121             // Bind the data efficiently with the holder.
122             holder.text.setText(DATA[position]);
123             holder.icon.setImageBitmap((position & 1) == 1 ? mIcon1 : mIcon2);
124 
125             return convertView;
126         }
127 
128         static class ViewHolder {
129             TextView text;
130             ImageView icon;
131         }
132     }
133 
134     @Override
onCreate(Bundle savedInstanceState)135     public void onCreate(Bundle savedInstanceState) {
136         super.onCreate(savedInstanceState);
137         setListAdapter(new EfficientAdapter(this));
138     }
139 
140     private static final String[] DATA = Cheeses.sCheeseStrings;
141 }
142