目录
- 导读
- 操作环境
- 源码
- 实例
导读
SimpleAdapter 是一个将 map 数据与 xml 文件中定义的 view 对应起来简易适配器。其对 BaseAdapter 的封装一定程度上简化了开发人员的使用门槛。
操作环境
- 操作系统:win7-64bit 旗舰版
- android 版本:android-23
- 模拟器:海马玩模拟器 0.9.0 Beta
源码
所有的 magic 在源码面前都显得那么裸露。
- 构造方法:
public SimpleAdapter(Context context, List<? extends Map<String, ?>> data,
@LayoutRes int resource, String[] from, @IdRes int[] to)
- getView 方法:
/**
* @see android.widget.Adapter#getView(int, View, ViewGroup)
*/
public View getView(int position, View convertView, ViewGroup parent) {
return createViewFromResource(mInflater, position, convertView, parent, mResource);
}
private View createViewFromResource(LayoutInflater inflater, int position, View convertView,
ViewGroup parent, int resource) {
View v;
if (convertView == null) {
v = inflater.inflate(resource, parent, false);
} else {
v = convertView;
}
bindView(position, v);
return v;
}
private void bindView(int position, View view) {
final Map dataSet = mData.get(position);
if (dataSet == null) {
return;
}
final ViewBinder binder = mViewBinder;
final String[] from = mFrom;
final int[] to = mTo;
final int count = to.length;
for (int i = 0; i < count; i++) {
final View v = view.findViewById(to[i]);
if (v != null) {
final Object data = dataSet.get(from[i]);
String text = data == null ? "" : data.toString();
if (text == null) {
text = "";
}
boolean bound = false;
if (binder != null) {
bound = binder.setViewValue(v, data, text);
}
if (!bound) {
if (v instanceof Checkable) {
if (data instanceof Boolean) {
((Checkable) v).setChecked((Boolean) data);
} else if (v instanceof TextView) {
// Note: keep the instanceof TextView check at the bottom of these
// ifs since a lot of views are TextViews (e.g. CheckBoxes).
setViewText((TextView) v, text);
} else {
throw new IllegalStateException(v.getClass().getName() +
" should be bound to a Boolean, not a " +
(data == null ? "<unknown type>" : data.getClass()));
}
} else if (v instanceof TextView) {
// Note: keep the instanceof TextView check at the bottom of these
// ifs since a lot of views are TextViews (e.g. CheckBoxes).
setViewText((TextView) v, text);
} else if (v instanceof ImageView) {
if (data instanceof Integer) {
setViewImage((ImageView) v, (Integer) data);
} else {
setViewImage((ImageView) v, text);
}
} else {
throw new IllegalStateException(v.getClass().getName() + " is not a " +
" view that can be bounds by this SimpleAdapter");
}
}
}
}
}
简单说明:
- SimpleAdpter 会将 String[] from, @IdRes int[] to 的元素一一对应起来
- 若 getView 方法中的第二个参数 View convertView 为 null,则通过 inflater.inflate(resource, parent, false); 创建一个新的;若非空的话,则沿用之前的 convertView;
- 对于 xml 中的视图类型,目前仅支持:
- Checkable 及其衍生类;如:CheckBoxes 等
- TextView 及其衍生类;如:TextView,EditText 等
- ImageView 及其衍生类;如:ImageView 等
实例
- test_item.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<!--红色背景-->
<TextView android:id="@+id/tv_content_1"
android:layout_width="match_parent"
android:layout_height="50dp"
android:background="#f00"
/>
<!--绿色背景-->
<TextView android:id="@+id/tv_content_2"
android:layout_width="match_parent"
android:layout_height="50dp"
android:background="#0f0"
/>
<!--蓝色背景-->
<TextView android:id="@+id/tv_content_3"
android:layout_width="match_parent"
android:layout_height="50dp"
android:background="#00f"
/>
</LinearLayout>
- test_simple_adapter.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ListView android:id="@+id/lv_test"
android:layout_width="match_parent"
android:layout_height="match_parent">
</ListView>
</LinearLayout>
- MainActivity.java:
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.test_simple_adapter);
this.testSimpleAdapter();
}
// 测试 SimpleAdapter
void testSimpleAdapter(){
// 从 xml 中找到 listview 控件
ListView lv = (ListView)this.findViewById(R.id.lv_test);
// 设置 数据集
ArrayList<HashMap<String, String>> data = new ArrayList<>();
for(int i =0; i<2; i++) {
HashMap<String, String> map = new HashMap<>();
map.put("key1", "value1_item_" + i);
map.put("key2", "value2_item_" + i);
map.put("key3", "value3_item_" + i);
data.add(map);
}
// 设置数据集中的键 和 test_item.xml 中对应的控件ID
String[] from = new String[]{"key1", "key2", "key3"};
@IdRes int[] to = new int[]{R.id.tv_content_1, R.id.tv_content_2, R.id.tv_content_3};
// 实例化适配器
SimpleAdapter sa = new SimpleAdapter(this, data, R.layout.test_item, from, to);
// 设置 listview 的适配器
lv.setAdapter(sa);
}
- 效果图: