通常在BaseAdapter.getView中会使用ViewHolder方式来缓存界面中的组件,以便提高性能.那我们可以定义一个DataViewHolder类
public class DataViewHolder {
HashMap mapView = new HashMap();
HashMap mapData = new HashMap();
public void setView(int key,View v){
this.mapView.put(key, v);
}
@SuppressWarnings("unchecked")
public T getView(int key){
return (T)this.mapView.get(key);
}
@SuppressWarnings("unchecked")
public T getView(Class clazz, int key){
return (T)this.mapView.get(key);
}
public void setData(String key, Object value){
mapData.put(key, value);
}
@SuppressWarnings("unchecked")
public T getData(String key){
return (T)mapData.get(key);
}
@SuppressWarnings("unchecked")
public T getData(Class clazz, String key){
return (T)mapData.get(key);
}
}
对界面组件入手时,我们需要一个方法来提供一组界面组件的ID号,便于在BaseAdapter.getView方法中获取该组件实例.
public int[] getFindViewByIDs() {
return new int[]{
R.id.ItemText,
R.id.ItemImage
};
}
在实现BaseAdapter.getView方法时,通常需要获取布局资源,那么我们提供一个方法
public View getLayout(int position, DataViewHolder vh) {
return inflater.inflate(R.layout.gv_content, null);
}
以便在BaseAdapter.getView方法中调用,我们来实现BaseAdapter.getView方法
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)); //资源id作为key,缓存界面中的组件
}
convertView.setTag(vh);
}
else
vh = (DataViewHolder)convertView.getTag();
this.renderData(position, vh); //继承类中的方法,完成数据到界面组件的赋值
return convertView;
}
public void renderData(int position, DataViewHolder vh) {
HashMap map = (HashMap)this.getItem(position);
vh.getView(TextView.class, R.id.ItemText).setText(map.get("title"));
ImageView imgView = vh.getView(R.id.ItemImage);
imgView.setImageURI(...);
}
public abstract class DataAdapter extends BaseAdapter {
protected LayoutInflater inflater=null;
protected Context mContext;
private List lst;
public DataAdapter(Context c, List 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 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类呢?我们还是要继承来实现.
public class T1Activity extends Activity {
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_t1);
HashMap map1 = new HashMap();
map1.put("title","xxx");
map1.put("url","xxx");
...
List> al = new ArrayList>();
al.add(map1); //添加数据
al.add(map2); //添加数据
...
PrgmAdapter adapter = new PrgmAdapter(T1Activity.this, al); //实例化数据适配器
GridView gridview=(GridView)findViewById(R.id.gridView1);
gridview.setAdapter(adapter);
}
//实际使用要继承来实现.现在我们不需要关心getView方法了(除非有特殊需求),只需要提供布局资源,组件资源号,并在renderData中完成赋值就OK了.
private class PrgmAdapter extends DataAdapter>{
public PrgmAdapter(Context c, List> lst){
super(c,lst);
}
@Override
public int[] getFindViewByIDs() {
return new int[]{
R.id.ItemText,
R.id.ItemImage
};
}
@Override
public View getLayout(int position, DataViewHolder vh) {
return this.getResourceView(R.layout.gv_content);
}
@Override
public void renderData(int position, DataViewHolder vh) {
HashMap map = this.getItemT(position);
vh.getView(TextView.class, R.id.ItemText).setText(map.get("title"));
ImageView imgView = vh.getView(R.id.ItemImage);
...
}
}
}
class StrAdapter extends DataAdapter{}
完全可以再进行调整,比如设置资源ID提供一个方法,在getView中使用.目前就可以基本使用满足通用性.
贴图:(都是使用上面定义的适配器)