android中继承BaseAdapter实现DataAdapter通用数据适配器

试想下,数据适配器只是提供不同的数据并匹配界面中的组件以呈现不同的数据内容.那么就可以对界面组件与数据项入手进行修改.

通常在BaseAdapter.getView中会使用ViewHolder方式来缓存界面中的组件,以便提高性能.那我们可以定义一个DataViewHolder类

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);
	}
}
对界面组件入手时,我们需要一个方法来提供一组界面组件的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;
	}


对数据项入手时,我们只需要定义泛型参数来支持,先暂时定义为HashMap<String,String>, renderData方法如下

public void renderData(int position, DataViewHolder vh) {
			HashMap<String,String> map = (HashMap<String,String>)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<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类呢?我们还是要继承来实现.

public class T1Activity extends Activity {
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_t1);

		HashMap<String,String> map1 = new HashMap<String,String>();
		map1.put("title","xxx");
		map1.put("url","xxx");
		...
		
		List<HashMap<String,String>> al = new ArrayList<HashMap<String,String>>();
		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<HashMap<String,String>>{
		public PrgmAdapter(Context c, List<HashMap<String,String>> 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<String,String> map = this.getItemT(position);
			vh.getView(TextView.class, R.id.ItemText).setText(map.get("title"));	
			ImageView imgView = vh.getView(R.id.ItemImage);	
			...
		}
	}
}

如果其他类型,例如String,则 
class StrAdapter extends DataAdapter<String>{}

完全可以再进行调整,比如设置资源ID提供一个方法,在getView中使用.目前就可以基本使用满足通用性.



贴图:(都是使用上面定义的适配器)

      

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值