转载请保留出处:http://www.eoeandroid.com/thread-72369-1-1.html
1 public View getView(int position, View convertView, ViewGroup parent) { 2 View view = new Xxx(...); 3 ... ... 4 return view; 5 }
描述: 以构造ListView的BaseAdapter为例,在BaseAdapter中提供了方法:
1 public View getView(int position, View convertView, ViewGroup parent) { 2 View view = null; 3 if (convertView != null) { 4 view = convertView; 5 ... 6 } else { 7 view = new Xxx(...); 8 ... 9 } 10 return view; 11 }
上述代码很好的解决了内存泄露的问题,使用convertView回收一些布局供下面重构是使用。
但是如果出现如下图的需求,convertView就不太好用了,convertView在Item为单一的布局时,能够回收并重用,但是多个Item布局时,convertView的回收和重用会出现问题。
官网解释如下,不解释了 Get the type of View that will be created by getView(int, android.view.View, android.view.ViewGroup)]getView(int, View, ViewGroup) for the specified item.
Parameters
position | The position of the item within the adapter's data set whose view type we want. |
Returns
- An integer representing the type of View. Two views should share the same type if one can be converted to the other in getView(int, android.view.View, android.view.ViewGroup)getView(int, View, ViewGroup). Note: Integers must be in the range 0 to getViewTypeCount() - 1. IGNORE_ITEM_VIEW_TYPE can also be returned.
Get the type of View that will be created by getView(int, android.view.View, android.view.ViewGroup)getView(int, View, ViewGroup) for the specified item.
Parameters
position | The position of the item within the adapter's data set whose view type we want. |
Returns
- An integer representing the type of View. Two views should share the same type if one can be converted to the other in getView(int, android.view.View, android.view.ViewGroup)getView(int, View, ViewGroup). Note: Integers must be in the range 0 to getViewTypeCount() - 1. IGNORE_ITEM_VIEW_TYPE can also be returned.
1 package com.bestv.listViewTest; 2 3 import java.util.ArrayList; 4 5 import android.app.Activity; 6 7 import android.content.Context; 8 9 import android.os.Bundle; 10 11 import android.util.Log; 12 13 import android.view.LayoutInflater; 14 15 import android.view.View; 16 17 import android.view.ViewGroup; 18 19 import android.widget.BaseAdapter; 20 21 import android.widget.CheckBox; 22 23 import android.widget.ImageView; 24 25 import android.widget.LinearLayout; 26 27 import android.widget.ListView; 28 29 import android.widget.TextView; 30 31 public class listViewTest extends Activity 32 { 33 34 /** Called when the activity is first created. */ 35 36 ListView listView; 37 38 MyAdapter listAdapter; 39 40 ArrayList<String> listString; 41 42 @Override 43 public void onCreate(Bundle savedInstanceState) 44 { 45 46 super.onCreate(savedInstanceState); 47 48 setContentView(R.layout.main); 49 50 listView = (ListView) this.findViewById(R.id.listview); 51 52 listString = new ArrayList<String>(); 53 54 for (int i = 0; i < 100; i++) 55 56 { 57 58 listString.add(Integer.toString(i)); 59 60 } 61 62 listAdapter = new MyAdapter(this); 63 64 listView.setAdapter(listAdapter); 65 66 } 67 68 class MyAdapter extends BaseAdapter 69 { 70 71 Context mContext; 72 73 LinearLayout linearLayout = null; 74 75 LayoutInflater inflater; 76 77 TextView tex; 78 79 final int VIEW_TYPE = 3; 80 81 final int TYPE_1 = 0; 82 83 final int TYPE_2 = 1; 84 85 final int TYPE_3 = 2; 86 87 public MyAdapter(Context context) 88 { 89 90 // TODO Auto-generated constructor stub 91 92 mContext = context; 93 94 inflater = LayoutInflater.from(mContext); 95 96 } 97 98 @Override 99 public int getCount() 100 { 101 102 // TODO Auto-generated method stub 103 104 return listString.size(); 105 106 } 107 108 //每个convert view都会调用此方法,获得当前所需要的view样式 109 110 @Override 111 public int getItemViewType(int position) 112 { 113 114 // TODO Auto-generated method stub 115 116 int p = position % 6; 117 118 if (p == 0) 119 120 return TYPE_1; 121 122 else if (p < 3) 123 124 return TYPE_2; 125 126 else if (p < 6) 127 128 return TYPE_3; 129 130 else 131 132 return TYPE_1; 133 134 } 135 136 @Override 137 public int getViewTypeCount() 138 { 139 140 // TODO Auto-generated method stub 141 142 return 3; 143 144 } 145 146 @Override 147 public Object getItem(int arg0) 148 { 149 150 // TODO Auto-generated method stub 151 152 return listString.get(arg0); 153 154 } 155 156 @Override 157 public long getItemId(int position) 158 { 159 160 // TODO Auto-generated method stub 161 162 return position; 163 164 } 165 166 @Override 167 public View getView(int position, View convertView, ViewGroup parent) 168 { 169 170 // TODO Auto-generated method stub 171 172 viewHolder1 holder1 = null; 173 174 viewHolder2 holder2 = null; 175 176 viewHolder3 holder3 = null; 177 178 int type = getItemViewType(position); 179 180 //无convertView,需要new出各个控件 181 182 if (convertView == null) 183 184 { 185 Log.e("convertView = ", " NULL"); 186 187 //按当前所需的样式,确定new的布局 188 189 switch (type) 190 191 { 192 193 case TYPE_1: 194 195 convertView = inflater.inflate(R.layout.listitem1, parent, false); 196 197 holder1 = new viewHolder1(); 198 199 holder1.textView = (TextView) convertView.findViewById(R.id.textview1); 200 201 holder1.checkBox = (CheckBox) convertView.findViewById(R.id.checkbox); 202 203 Log.e("convertView = ", "NULL TYPE_1"); 204 205 convertView.setTag(holder1); 206 207 break; 208 209 case TYPE_2: 210 211 convertView = inflater.inflate(R.layout.listitem2, parent, false); 212 213 holder2 = new viewHolder2(); 214 215 holder2.textView = (TextView) convertView.findViewById(R.id.textview2); 216 217 Log.e("convertView = ", "NULL TYPE_2"); 218 219 convertView.setTag(holder2); 220 221 break; 222 223 case TYPE_3: 224 225 convertView = inflater.inflate(R.layout.listitem3, parent, false); 226 227 holder3 = new viewHolder3(); 228 229 holder3.textView = (TextView) convertView.findViewById(R.id.textview3); 230 231 holder3.imageView = (ImageView) convertView.findViewById(R.id.imageview); 232 233 Log.e("convertView = ", "NULL TYPE_3"); 234 235 convertView.setTag(holder3); 236 237 break; 238 239 } 240 241 } 242 243 else 244 245 { 246 247 //有convertView,按样式,取得不用的布局 248 249 switch (type) 250 251 { 252 253 case TYPE_1: 254 255 holder1 = (viewHolder1) convertView.getTag(); 256 257 Log.e("convertView !!!!!!= ", "NULL TYPE_1"); 258 259 break; 260 261 case TYPE_2: 262 263 holder2 = (viewHolder2) convertView.getTag(); 264 265 Log.e("convertView !!!!!!= ", "NULL TYPE_2"); 266 267 break; 268 269 case TYPE_3: 270 271 holder3 = (viewHolder3) convertView.getTag(); 272 273 Log.e("convertView !!!!!!= ", "NULL TYPE_3"); 274 275 break; 276 277 } 278 279 } 280 281 //设置资源 282 283 switch (type) 284 285 { 286 287 case TYPE_1: 288 289 holder1.textView.setText(Integer.toString(position)); 290 291 holder1.checkBox.setChecked(true); 292 293 break; 294 295 case TYPE_2: 296 297 holder2.textView.setText(Integer.toString(position)); 298 299 break; 300 301 case TYPE_3: 302 303 holder3.textView.setText(Integer.toString(position)); 304 305 holder3.imageView.setBackgroundResource(R.drawable.icon); 306 307 break; 308 309 } 310 311 return convertView; 312 313 } 314 315 } 316 317 //各个布局的控件资源 318 319 class viewHolder1 320 { 321 322 CheckBox checkBox; 323 324 TextView textView; 325 326 } 327 328 class viewHolder2 329 { 330 331 TextView textView; 332 333 } 334 335 class viewHolder3 336 { 337 338 ImageView imageView; 339 340 TextView textView; 341 342 } 343 344 }
在getView()中需要将不同布局进行缓存和适配,系统在判断是否有convertView时,会自动去调用getItemViewType (int position) ,查看是否已经有缓存的该类型的布局,从而进入if(convertView == null)和else{}的判断。期间需要做的是convertView.setTag(holder3),以便在convertView重用时可以直接拿到该布局的控件,holder3 = (viewHolder3) convertView.getTag()。到这一步,convertView的回收和重用就已经写好了,接下来只需要对你的不同的控件进行设置就行了。