Android之Adapter系列之SimpleAdapter类

SimpleAdapter继承了BaseAdapter,作为一个Adapter的简单实现,SimpleAdapter支持的控件也比较少:checkable控件(例如checkbox,radioButton)、TextView和ImageView。

源码部分

源码路径:framework\base\core\java\android\widget\SimpleAdapter.java

package android.widget;

import android.content.Context;
import android.view.View;
import android.view.ViewGroup;
import android.view.LayoutInflater;
import android.net.Uri;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
  * SimpleAdapter是一个将静态数据映射到在xml中定义的View上的简单的adapter。
  * 开发者将数据保存在一个包含maps的ArrayList中。Arraylist中的每一项数据和view
  * 中的每一个项对应。map中包含了view中每一行的数据。同样,开发者可以指定xml文件
  * 来显示map中对应行的数据或者用map中的keys值来指定view。
  *
  * 数据的绑定发生在一下两种情况。
  * 首先,如果{@link android.widget.SimpleAdapter.ViewBinder} 可见,
  * {@link ViewBinder#setViewValue(android.view.View, Object, String)}被调用。
  * 如果setViewValue返回true,那么则进行数据绑定。如果返回false,那么下面这些
  * 情况将按顺序尝试执行
  * 
    *
  • 如果View实现了Checkable(例如Checkbox),那么返回值将是boolean类型 *
  • TextView 返回值为String并且 {@link #setViewText(TextView, String)}将被调用 *
  • ImageView 返回值为资源id或者string,并且{@link #setViewImage(ImageView, int)} * 或者 {@link #setViewImage(ImageView, String)} 被调用 *
* 如果没有合适的binding返回,将会抛出 {@link IllegalStateException}异常 */ public class SimpleAdapter extends BaseAdapter implements Filterable { private int[] mTo; private String[] mFrom; private ViewBinder mViewBinder; private List> mData; private int mResource; private int mDropDownResource; private LayoutInflater mInflater; private SimpleFilter mFilter; private ArrayList> mUnfilteredData; /** * 构造函数 * * @param context SimpleAdapter运行的上下文 * @param data 包含map的list列表。列表中给的每一项和view中的每一个item对应。Maps中则包含View * 中每一行的所有数据,并且应该包含“from”中所有指定的项 * @param resource View中item的layout布局id,该view至少包含“to”中指定的项 * * @param from 一个将要被添加到map中的列名列表,和map中的每一个item对应 * @param to 需要显示view的id和“from”参数对应。必须全是TextView。 * */ public SimpleAdapter(Context context, List> data, int resource, String[] from, int[] to) { mData = data; mResource = mDropDownResource = resource; mFrom = from; mTo = to; mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); } /** * @see android.widget.Adapter#getCount() */ public int getCount() { return mData.size(); } /** * @see android.widget.Adapter#getItem(int) */ public Object getItem(int position) { return mData.get(position); } /** * @see android.widget.Adapter#getItemId(int) */ public long getItemId(int position) { return position; } /** * getView直接调用createViewFromResource */ public View getView(int position, View convertView, ViewGroup parent) { return createViewFromResource(position, convertView, parent, mResource); } /** * greateViewFromResource进行了convertView的判断后,调用bindView来进行具体view的绑定 */ private View createViewFromResource(int position, View convertView, ViewGroup parent, int resource) { View v; if (convertView == null) { v = mInflater.inflate(resource, parent, false); } else { v = convertView; } bindView(position, v); return v; } /** * 设置用来创建drop down 视图的布局id * @param resource 定义了drop down 视图的资源文件 * @see #getDropDownView(int, android.view.View, android.view.ViewGroup) */ public void setDropDownViewResource(int resource) { this.mDropDownResource = resource; } /** * 同样调用createViewFromResource来生成对应的view */ @Override public View getDropDownView(int position, View convertView, ViewGroup parent) { return createViewFromResource(position, convertView, parent, mDropDownResource); } /** * bindview应该是SimpleAdapter中核心的方法其中position为需要获取的view的位置,view为convertView */ 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 ? "" : 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"); } } } } } /** * 返回一个ViewBinder */ public ViewBinder getViewBinder() { return mViewBinder; } /** * 设置ViewBinder */ public void setViewBinder(ViewBinder viewBinder) { mViewBinder = viewBinder; } /** * 该方法除被宾得View调用,用来给ImageView设置图片 * 如果ViewBinder不存在或者ViewBinder无法和ImageView绑定 */ public void setViewImage(ImageView v, int value) { v.setImageResource(value); } /** * 该方法被bindView调用,用来给ImageView设置图片 * 如果ViewBinder不存在或者ViewBinder无法和ImageView绑定 * * 默认情况下value被当作image资源,如果无法被当作image资源,那么将会被当作image uri */ public void setViewImage(ImageView v, String value) { try { v.setImageResource(Integer.parseInt(value)); } catch (NumberFormatException nfe) { v.setImageURI(Uri.parse(value)); } } /** * 该方法被bindView调用,用来给TextView色获知字符 * 如果ViewBinder不存在或者ViewBinder无法和TextView绑定 */ public void setViewText(TextView v, String text) { v.setText(text); } public Filter getFilter() { if (mFilter == null) { mFilter = new SimpleFilter(); } return mFilter; } /** * 这个内部静态接口被外部SimpleAdapter客户端用来修改views * 开发者通过实现这个接口,来修改view,如果这些View不能直接被SIM所支持, * 或者修改view绑定的方式 * @see SimpleAdapter#setViewImage(ImageView, int) * @see SimpleAdapter#setViewImage(ImageView, String) * @see SimpleAdapter#setViewText(TextView, String) */ public static interface ViewBinder { /** * 绑定指定的数据到指定的view上 * 如果binding被该方法处理,那么该方法必须返回true,如果返回false,那么SimpleAdapter * 将会自己处理binding过程 * @param view the view to bind the data to * @param data the data to bind to the view * @param textRepresentation a safe String representation of the supplied data: * it is either the result of data.toString() or an empty String but it * is never null * * @return true if the data was bound to the view, false otherwise */ boolean setViewValue(View view, Object data, String textRepresentation); } /** * 一个包含了某个前缀的数组过滤器,如果list中的每一项不包含该前缀,那么将会从该list中移除 */ private class SimpleFilter extends Filter { @Override protected FilterResults performFiltering(CharSequence prefix) { FilterResults results = new FilterResults(); if (mUnfilteredData == null) { mUnfilteredData = new ArrayList>(mData); } if (prefix == null || prefix.length() == 0) { ArrayList> list = mUnfilteredData; results.values = list; results.count = list.size(); } else { String prefixString = prefix.toString().toLowerCase(); ArrayList> unfilteredValues = mUnfilteredData; int count = unfilteredValues.size(); ArrayList> newValues = new ArrayList>(count); for (int i = 0; i < count; i++) { Map h = unfilteredValues.get(i); if (h != null) { int len = mTo.length; for (int j=0; j>) results.values; if (results.count > 0) { notifyDataSetChanged(); } else { notifyDataSetInvalidated(); } } } }

事例部分

list_item.xml




    

    

        

        
    


SimpleAdapter中包含了一个Interface ViewBinder,这里分两种情况,分别介绍两个事例,第一个,不使用ViewBinder;第二个,使用ViewBinder

SimpleAdapterNoBinder.java

package com.lj.simpleadaptertest;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;

import android.app.Activity;
import android.os.Bundle;
import android.widget.ListView;
import android.widget.SimpleAdapter;

public class SimpleAdapterNoBinder extends Activity {

	ListView mListView;
	List> mData = new ArrayList>();
	public static final String KEY_IMG = "imgage";
	public static final String KEY_TITLE = "title";
	public static final String KEY_SUMMARY = "summary";

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_no_binder);
		mListView = (ListView) findViewById(R.id.list_no_binder);
               //定义一个mAdapter,设置自定义的layout布局,调用getData返回需要显示的数据
		SimpleAdapter mAdapter = new SimpleAdapter(this, getData(),
				R.layout.list_item, new String[] { KEY_IMG, KEY_TITLE,
						KEY_SUMMARY, }, new int[] { R.id.image, R.id.title,
						R.id.summary });
		mListView.setAdapter(mAdapter);
	}
       //map中包含三部分数据,ImageView设置为默认的R.drawable.ic_launcher,两个TextView设置为随机的字符
	private List> getData() {
		List> list = new ArrayList>();
		Map map;
		for (int i = 0; i < 30; i++) {
			map = new HashMap();
			map.put(KEY_IMG, R.drawable.ic_launcher);
			map.put(KEY_TITLE, getTitleText(8));
			map.put(KEY_SUMMARY, getTitleText(10));
			list.add(map);
		}
		return list;
	}

	private Object getTitleText(int length) {
		String mString = "qwertyuiopasdfghjklzxcvbnm";
		Random random = new Random();
		StringBuffer sb = new StringBuffer();
		for (int i = 0; i < length; i++) {
			int number = random.nextInt(mString.length());
			sb.append(mString.charAt(number));
		}
		return sb.toString();
	}
}
SimpleAdapterWithBinder.java

package com.lj.simpleadaptertest;

import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;

import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Color;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.SimpleAdapter;
import android.widget.TextView;

public class SimpleAdapterWithBinder extends Activity {

	ListView mListView;
	List> mData = new ArrayList>();
	public static final String KEY_IMG = "imgage";
	public static final String KEY_TITLE = "title";
	public static final String KEY_SUMMARY = "summary";
	public static final String KEY_CHECK = "check";

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_no_binder);
		mListView = (ListView) findViewById(R.id.list_no_binder);
		SimpleAdapter mAdapter = new SimpleAdapter(this, getData(),
				R.layout.list_item, new String[] { KEY_IMG, KEY_TITLE,
						KEY_SUMMARY, }, new int[] { R.id.image, R.id.title,
						R.id.summary });
		mAdapter.setViewBinder(new TestViewBinder());
		mListView.setAdapter(mAdapter);
	}

	private List> getData() {
		List> list = new ArrayList>();
		Map map;
		for (int i = 0; i < 30; i++) {
			map = new HashMap();
			map.put(KEY_IMG, R.drawable.ic_launcher);
			map.put(KEY_TITLE, getTitleText(8));
			map.put(KEY_SUMMARY, getTitleText(10));
			map.put(KEY_CHECK, (i / 2 == 0 ? true : false));
			list.add(map);
		}
		return list;
	}

	private Object getTitleText(int length) {
		String mString = "qwertyuiopasdfghjklzxcvbnm";
		Random random = new Random();
		StringBuffer sb = new StringBuffer();
		for (int i = 0; i < length; i++) {
			int number = random.nextInt(mString.length());
			sb.append(mString.charAt(number));
		}
		return sb.toString();
	}

	public Bitmap getBitmap(final String url) {
		Log.e("lijian", "url = " + url);
		Bitmap bmp = null;

		try {
			URL mUrl = new URL(url);
			HttpURLConnection conn = (HttpURLConnection) mUrl.openConnection();
			InputStream is = conn.getInputStream();
			bmp = BitmapFactory.decodeStream(is);
		} catch (Exception e) {

			e.printStackTrace();
		}

		return bmp;
	}

	/**
	 * 实现ViewBinder接口
	 * 
	 */
	class TestViewBinder implements SimpleAdapter.ViewBinder {

		@Override
		public boolean setViewValue(View view, Object data,
				String textRepresentation) {
			if ((view instanceof ImageView)) {

				Log.e("lijian", "set internet image data " + data);
				ImageView mImageView = (ImageView) view;
				mImageView.setImageResource(R.drawable.error);
				return true;
			} else if (view instanceof TextView && view.getId() ==R.id.summary) {
				TextView mTextView = (TextView) view;
				mTextView.setText("你好");
				return true;
			}

			return false;
		}

	}

}

效果图:

Android之Adapter系列之SimpleAdapter类_第1张图片

 图 1

Android之Adapter系列之SimpleAdapter类_第2张图片

图二

事例总结

图片以和图片二分别代表不使用ViewBinder和使用ViewBinder的结果,每一个Item的图片和summary字符可以在ViewBinder实现的类中的setViewValue中修改。

源码下载

你可能感兴趣的:(android)