原文出处:http://blog.csdn.net/javasuki/article/details/11869615
说明:为了便于以后拿来就用,在作者的基础上进行了代码修复和补充
试想下,数据适配器只是提供不同的数据并匹配界面中的组件以呈现不同的数据内容.那么就可以对界面组件与数据项入手进行修改.
通常在BaseAdapter.getView中会使用ViewHolder方式来缓存界面中的组件,以便提高性能.那我们可以定义一个DataViewHolder类
让我们来看一下完整的实现
要首先在layout中定义一个list_view.xml布局文件,如下:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity" > <ListView android:scrollbars="none" android:id="@+id/lv_list_view" android:layout_width="wrap_content" android:layout_height="wrap_content" /> </RelativeLayout>
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/RelativeLayout01" android:layout_width="fill_parent" android:layout_height="wrap_content" android:paddingBottom="4dip" android:paddingLeft="12dip" android:paddingRight="12dip" > <ImageView android:id="@+id/ItemImage" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentRight="true" android:paddingTop="12dip" /> <TextView android:id="@+id/ItemText" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_below="@+id/ItemImage" android:text="TextView02" /> </RelativeLayout>
定义一个DataViewHolder的类
import java.util.HashMap; import android.view.View; public class DataViewHolder { HashMap<Integer,View> mapView = new HashMap<Integer,View>(); HashMap<String,Object> mapData = new HashMap<String,Object>(); public void setView(int key,View v){ this.mapView.put(key, v); } @SuppressWarnings("unchecked") public <T> T getView(int key){ return (T)this.mapView.get(key); } @SuppressWarnings("unchecked") public <T> T getView(Class<T> clazz, int key){ return (T)this.mapView.get(key); } public void setData(String key, Object value){ mapData.put(key, value); } @SuppressWarnings("unchecked") public <T> T getData(String key){ return (T)mapData.get(key); } @SuppressWarnings("unchecked") public <T> T getData(Class<T> clazz, String key){ return (T)mapData.get(key); } }
定义一个DataAdapter的类继承BaseAdapter,实现自定义通用适配
import java.util.List; import android.content.Context; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.BaseAdapter; public abstract class DataAdapter<TItem> extends BaseAdapter { protected LayoutInflater inflater = null; protected Context mContext; private List<TItem> lst; public DataAdapter(Context c, List<TItem> lst) { this.mContext = c; this.lst = lst; this.inflater = LayoutInflater.from(c); } @Override public int getCount() { return lst.size(); } public void insert(TItem data) { lst.add(0, data); this.notifyDataSetChanged(); } public void append(TItem data) { lst.add(data); this.notifyDataSetChanged(); } public void replace(TItem data) { int idx = this.lst.indexOf(data); this.replace(idx, data); } public void replace(int index, TItem data) { if (index < 0) { return; } if (index > lst.size() - 1) { return; } lst.set(index, data); this.notifyDataSetChanged(); } public List<TItem> getItems() { return lst; } @Override public Object getItem(int position) { return lst.get(position); } public TItem getItemT(int position) { return lst.get(position); } @Override public long getItemId(int position) { return position; } public void removeItem(int position) { if (lst.size() <= 0) { return; } if (position < 0) { return; } if (position > lst.size() - 1) { return; } lst.remove(position); this.notifyDataSetChanged(); } public void clear() { lst.clear(); this.notifyDataSetChanged(); } public abstract int[] getFindViewByIDs(); public abstract View getLayout(int position, DataViewHolder vh); public final View getResourceView(int id) { return inflater.inflate(id, null); } @Override public View getView(int position, View convertView, ViewGroup parent) { DataViewHolder vh; if (convertView == null) { vh = new DataViewHolder(); convertView = this.getLayout(position, vh); if (convertView == null) { return null; } int[] idAry = this.getFindViewByIDs(); if (idAry == null) { idAry = new int[] {}; } for (int id : idAry) { vh.setView(id, convertView.findViewById(id)); } convertView.setTag(vh); } else { vh = (DataViewHolder) convertView.getTag(); } this.renderData(position, vh); return convertView; } public abstract void renderData(int position, DataViewHolder vh); }
实际使用,如何使用DataAdapter类呢?我们还是要继承来实现,如果要实现条目的点击事件,需要实现OnItemClick接口
import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import android.os.Bundle; import android.app.Activity; import android.content.Context; import android.view.View; import android.widget.AdapterView; import android.widget.AdapterView.OnItemClickListener; import android.widget.ImageView; import android.widget.ListView; import android.widget.TextView; import android.widget.Toast; public class MainActivity extends Activity implements OnItemClickListener{ //为了避免发生类型转化错误,HashMap中的值推荐使用Object类型 private List<HashMap<String, Object>> list; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.list_view); list = new ArrayList<HashMap<String, Object>>(); for (int i = 0; i < 20; i++) { Map<String, Object> map = new HashMap<String, Object>(); map.put("title", "标题"+i); map.put("image", R.drawable.ic_launcher + ""); list.add((HashMap<String, Object>) map); } PrgmAdapter adapter = new PrgmAdapter(MainActivity.this, list);// 实例化数据适配器 ListView lv_list_view1 = (ListView) findViewById(R.id.lv_list_view); lv_list_view1.setAdapter(adapter); lv_list_view1.setOnItemClickListener(this); } private class PrgmAdapter extends DataAdapter<HashMap<String, Object>> { public PrgmAdapter(Context c, List<HashMap<String, Object>> lst) { super(c, lst); } @Override public int[] getFindViewByIDs() { return new int[] { R.id.ItemImage, R.id.ItemText }; } @Override public View getLayout(int position, DataViewHolder vh) { return this.getResourceView(R.layout.list_view_item); } @Override public void renderData(int position, DataViewHolder vh) { HashMap<String, Object> map = this.getItemT(position); vh.getView(TextView.class, R.id.ItemText).setText(map.get("title").toString()); vh.getView(ImageView.class, R.id.ItemImage).setImageResource( Integer.parseInt(map.get("image").toString())); } } @Override public void onItemClick(AdapterView<?> adapterview, View view, int i, long l) { Toast.makeText(MainActivity.this, "你选中了:"+list.get(i).get("title"), 1).show(); } }
完全可以再进行调整,比如设置资源ID提供一个方法,在getView中使用.目前就可以基本使用满足通用性.
贴图:(都是使用上面定义的适配器)