1.什么是数据适配器?
用来建立数据源和数据渲染控件之间的关系,将数据的来源和数据的显示之间进行解耦,降低耦合性
2.BaseAdapter接口
BaseAdapter是一个抽象类(abstract)【以下代码为android源码】
public abstract class BaseAdapter implements ListAdapter, SpinnerAdapter {
private final DataSetObservable mDataSetObservable = new DataSetObservable();
private CharSequence[] mAutofillOptions;
public boolean hasStableIds() {
return false;
}
public void registerDataSetObserver(DataSetObserver observer) {
mDataSetObservable.registerObserver(observer);
}
public void unregisterDataSetObserver(DataSetObserver observer) {
mDataSetObservable.unregisterObserver(observer);
}
/**
* Notifies the attached observers that the underlying data has been changed
* and any View reflecting the data set should refresh itself.
*/
public void notifyDataSetChanged() {
mDataSetObservable.notifyChanged();
}
/**
* Notifies the attached observers that the underlying data is no longer valid
* or available. Once invoked this adapter is no longer valid and should
* not report further data set changes.
*/
public void notifyDataSetInvalidated() {
mDataSetObservable.notifyInvalidated();
}
public boolean areAllItemsEnabled() {
return true;
}
public boolean isEnabled(int position) {
return true;
}
public View getDropDownView(int position, View convertView, ViewGroup parent) {
return getView(position, convertView, parent);
}
public int getItemViewType(int position) {
return 0;
}
public int getViewTypeCount() {
return 1;
}
public boolean isEmpty() {
return getCount() == 0;
}
@Override
public CharSequence[] getAutofillOptions() {
return mAutofillOptions;
}
/**
* Sets the value returned by {@link #getAutofillOptions()}
*/
public void setAutofillOptions(@Nullable CharSequence... options) {
mAutofillOptions = options;
}
}
需要实现的抽象方法有四种
public int getCount() 适配器中数据集中数据的个数 listview显示的总数据 public Object getItem(int position) 获取数据集中与指定索引对应的数据项 public long getItemId(int position) 获取指定行对应的id public View getView(int position,View convertView,ViewGroup parent):获取每一个Item显示的内容
3.如何使用BaseAdapter和ListView进行联动?
3-1:准备含ListView的总布局文件
3-2:准备ListView中呈现的item的布局()
3-3:构建数据源:
package com.app.baseadaptertraining;
//构建数据源
public class ItemBean {
public int itemImageResId;
public String itemTitle;
public String itemContent;
//添加构造方法
public ItemBean(int itemImageResId, String itemTitle, String itemContent) {
this.itemImageResId = itemImageResId;
this.itemTitle = itemTitle;
this.itemContent = itemContent;
}
}
3-4:实现数据适配器(可优化)
package com.app.baseadaptertraining;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;
import java.util.List;
/**
* BaseAdapter 抽象类
*/
public class MyAdapter extends BaseAdapter {
private List mList;
private LayoutInflater mInflater;
//进行数据的初始化
//将数据源和数据适配器之间进行关联
public MyAdapter(Context context, List list) {
mList = list;
mInflater = LayoutInflater.from(context);
}
//返回ListView中的数据量
@Override
public int getCount() {
return mList.size();
}
//取得所含有的数据项
@Override
public Object getItem(int position) {
return mList.get(position);
}
//返回数据项的索引
@Override
public long getItemId(int position) {
return position;
}
//返回每一项的内容
//没有缓存机制
@Override
public View getView(int position, View convertView, ViewGroup parent) {
//可以将xml文件装换称为view
//开始装载视图
/**
* 每一次都是创建新的view,没有实现缓存机制 实现资源的极大浪费
* 效率极其低下
* View view=mInflater.inflate(R.layout.item,null);
* //找到视图中的三个控件
* ImageView imageView=(ImageView) view.findViewById(R.id.iv_image);
* TextView title=(TextView)view.findViewById(R.id.tv_title);
* TextView content=(TextView)view.findViewById(R.id.tv_content);
* ItemBean bean=mList.get(position);
* //开始进行数据的填充
* imageView.setImageResource(bean.itemImageResId);
* title.setText(bean.itemTitle);
* content.setText(bean.itemContent);
* */
//*******************************************************************
//第一种优化方案:避免重复去创建view对象 但是fingViewById依旧会浪费大量的时间
// if (convertView == null) {
// convertView = mInflater.inflate(R.layout.item, null);
// }
// ImageView imageView = (ImageView) convertView.findViewById(R.id.iv_image);
// TextView title = (TextView) convertView.findViewById(R.id.tv_title);
// TextView content = (TextView) convertView.findViewById(R.id.tv_content);
// ItemBean bean = mList.get(position);
// //开始进行数据的填充
// imageView.setImageResource(bean.itemImageResId);
// title.setText(bean.itemTitle);
// content.setText(bean.itemContent);
// return convertView;
//*********************************************************************
//第二种优化方案
//1.避免convertView以及findViewById的优化
//ViewHolder
ViewHolder viewHolder;
if (convertView == null) {
viewHolder = new ViewHolder();
convertView = mInflater.inflate(R.layout.item, null);
//载入数据 findViewById()
viewHolder.imageView = (ImageView) convertView.findViewById(R.id.iv_image);
viewHolder.content = (TextView) convertView.findViewById(R.id.tv_content);
viewHolder.title = (TextView) convertView.findViewById(R.id.tv_title);
//ViewHolder和convertView进行关联
convertView.setTag(viewHolder);
} else {
//取出关联的ViewHolder对象
viewHolder = (ViewHolder) convertView.getTag();
}
ItemBean bean = mList.get(position);
//开始进行数据的填充
viewHolder.imageView.setImageResource(bean.itemImageResId);
viewHolder.title.setText(bean.itemTitle);
viewHolder.content.setText(bean.itemContent);
return convertView;
}
//避免重复进行findViewById()
//建立映射条件
class ViewHolder {
//对应布局中的三个控件
public ImageView imageView;
public TextView title;
public TextView content;
}
}
3-5:构建数据适配器和数据渲染器之间的联系(setAdapter)
package com.app.baseadaptertraining;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.ListView;
import java.util.ArrayList;
import java.util.List;
/**
* 1.准备含ListView的总布局文件
* 2.准备单独的item文件
* 3.构造数据源(bean/pojo)
* 4.实现数据适配器 BaseAdapter
* 5.建立Adapter和ListView之间的联系
*/
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
createMyList();
}
private void createMyList() {
List itemBeanList = new ArrayList<>();
//封装数据(准备假的数据)
for (int i = 0; i < 20; i++) {
//进行数据的填充
itemBeanList.add(new ItemBean(R.mipmap.ic_launcher, "这是一个title" + i, "这是一个content" + i));
}
//建立Adapter和ListView的联系
ListView listView = (ListView) findViewById(R.id.lv_main);
listView.setAdapter(new MyAdapter(this, itemBeanList));
}
}
4.谈谈优化(主要是在构建Adapter的getView方法)
下面给出三种方案来构建视图
方案1:无优化,每一次均创建新的view,没有实现相应的缓存机制,实现资源的极大浪费
public View getView(int position, View convertView, ViewGroup parent) {
//可以将xml文件装换称为view
//开始装载视图
/**
* 每一次都是创建新的view,没有实现缓存机制 实现资源的极大浪费
* 效率极其低下
* View view=mInflater.inflate(R.layout.item,null);
* //找到视图中的三个控件
* ImageView imageView=(ImageView) view.findViewById(R.id.iv_image);
* TextView title=(TextView)view.findViewById(R.id.tv_title);
* TextView content=(TextView)view.findViewById(R.id.tv_content);
* ItemBean bean=mList.get(position);
* //开始进行数据的填充
* imageView.setImageResource(bean.itemImageResId);
* title.setText(bean.itemTitle);
* content.setText(bean.itemContent);
return view;
* */}
方案2:部分优化,借助自带的convertView进行优化
(判断convertView是否为空,从而杜绝每一次都要构建view的情况,但是重复findViewById()依旧会消耗极大的内存)
if (convertView == null) {
convertView = mInflater.inflate(R.layout.item, null);
}
ImageView imageView = (ImageView) convertView.findViewById(R.id.iv_image);
TextView title = (TextView) convertView.findViewById(R.id.tv_title);
ItemBean bean = mList.get(position);
//开始进行数据的填充
imageView.setImageResource(bean.itemImageResId);
title.setText(bean.itemTitle);
content.setText(bean.itemContent);
return convertView;
方案3:全局优化,使用ViewHolder和convertView达到一种比较好的优化效果(相当于建立了两个缓存机制)
如果存在了视图组件,使用现成的convertView,无需重新创建
如果存在了控件,使用ViewHolder. 进行调用,无需重新查找控件位置
@Override
public View getView(int position, View convertView, ViewGroup parent) {
//1.避免convertView以及findViewById的优化
//ViewHolder
ViewHolder viewHolder;
if (convertView == null) {
viewHolder = new ViewHolder();
convertView = mInflater.inflate(R.layout.item, null);
//载入数据 findViewById()
viewHolder.imageView = (ImageView) convertView.findViewById(R.id.iv_image);
viewHolder.content = (TextView) convertView.findViewById(R.id.tv_content);
viewHolder.title = (TextView) convertView.findViewById(R.id.tv_title);
//ViewHolder和convertView进行关联
convertView.setTag(viewHolder);
} else {
//取出关联的ViewHolder对象
viewHolder = (ViewHolder) convertView.getTag();
}
ItemBean bean = mList.get(position);
//开始进行数据的填充
viewHolder.imageView.setImageResource(bean.itemImageResId);
viewHolder.title.setText(bean.itemTitle);
viewHolder.content.setText(bean.itemContent);
return convertView;
}
//避免重复进行findViewById()
//建立映射条件
class ViewHolder {
//对应布局中的三个控件
public ImageView imageView;
public TextView title;
public TextView content;
}