关于ListView (2)——SimpleAdapter源码解析与ViewBinders的用法

 如题,这里主要讲解 SimpleAdapter的源码, ViewBinders只是作为该类的一个知识点。

说到android源码,很多人看下去可能会开始觉得头越来越晕,最后就不了了之。不过理解源码确实能让自己更深入的了解android的运作,更顺手的写出优秀的代码。其实看android源码,一开始不一定就立即从重要或者核心开始下手,即使能够看下去,也会很累,浪费的时间也多。就如解剖一只牛,让我来,我就会先一刀一刀去掉外层的肉(因为我不是那种经验丰富的人),先从简单的,一层一层剥开,牛肉慢慢的去掉,开始可以看到整个骨架了。这样既不会很快失去耐心,又能挑起自己继续学习下去的欲望,虽然这种方法是很慢的,但是过程明白了,以后就可以快。当然剩下的骨头也不容易啃 :),不过至少轻松很多。

       这里讲解的例子主要是跟别人的结合在一起说,引用的文章链接:http://mgmblog.com/2008/12/29/simpleadapter-viewbinders/

        SimpleAdapter toolsAdapter =

               new SimpleAdapter(

                       this,

                       _activityNames,

                       R.layout.row,

                       new String[] { ACTIVITY_NAME_ENTRY },

                       new int[] { R.id.text1 } );

       这是创建SimpleAdapter的一段代码,先不要理那些变量。当运行这段代码时,会有如下操作:

  

  
    
public SimpleAdapter(Context context, List <? extends Map < String, ?>> data,
int resource, String[] from, int [] to) {
mData
= data;
mResource
= mDropDownResource = resource;
mFrom
= from;
mTo
= to;
mInflater
= (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}

SimpleAdapter下面的源码跟继承重写BaseAdapter里面的方法差不多。

  
    
/* *
* @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;
}

/* *
* @see android.widget.Adapter#getView(int, View, ViewGroup)
*/
public View getView( int position, View convertView, ViewGroup parent) {
return createViewFromResource(position, convertView, parent, mResource);
}
// 这里提高listview的效率
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;
}

// bindView是重点,主要是将你前面传入给item的xml文件解析,然后判断是Checkable还是TextView或者是ImageView,做出相应的处理。

  
    
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 " );
}
}
}
}
}

这段代码主要是针对特殊数据做处理

boolean bound = false;

if (binder != null) {

          bound = binder.setViewValue(v, data, text);

}

 

SimpleAdapter的基本解析就到这里。

现在结合那篇文章说说剩下的一点(ViewBinders)。

 

重写TextView,触发按键会跳转到另一个intent

 

  
    
/// //ToolNameView.java
public class ToolNameView extends TextView
{
private Intent _intentToLaunch;

public ToolNameView(Context context, AttributeSet attrs, int defStyle)
{
super(context, attrs, defStyle);
setupView();
}

public ToolNameView(Context context, AttributeSet attrs)
{
super(context, attrs);
setupView();
}

public ToolNameView(Context context)
{
super(context);
setupView();
}

private void setupView()
{
this .setOnClickListener( new OnClickListener()
{
public void onClick(View v)
{
getContext().startActivity( _intentToLaunch );
}
});
}

public void setIntentToLaunch( Intent intent )
{
_intentToLaunch
= intent;
}

}

/// // layout/row.xml
<? xml version = " 1.0 " encoding = " utf-8 " ?>
< LinearLayout
xmlns:android
= " http://schemas.android.com/apk/res/android "
android:id
= " @+id/vw1 "
android:layout_width
= " fill_parent "
android:layout_height
= " wrap_content "
android:orientation
= " horizontal " >

< com.mgm.android.toolbox.ToolNameView
android:id
= " @+id/text1 "
android:textSize
= " 16sp "
android:textStyle
= " bold "
android:layout_width
= " fill_parent "
android:layout_height
= " wrap_content "
android:padding
= " 3dip " />

</ LinearLayout >

//////
class ToolboxRow
{
private Intent _intentToLaunch;
private String _name;

public ToolboxRow( Intent intentToLaunch, String name )
{
_intentToLaunch
= intentToLaunch;
_name
= name;
}

public Intent getIntentToLaunch()
{
return _intentToLaunch;
}

public String getName()
{
return _name;
}
}

ArrayList<HashMap<String, ToolboxRow>> _activityNames;

 

////添加name和intent到数据源_activityNames

 

  
    
/* *

* DON'T FORGET TO ALSO ADD ACTIVITY TO MANIFEST!!

*

* @param name

* @param intentToLaunch

*/

private void addActivityToList( String name, Intent intentToLaunch )

{

HashMap entry
= new HashMap();

ToolboxRow row
= new ToolboxRow( intentToLaunch, name );

entry.put( ACTIVITY_NAME_ENTRY, row );



_activityNames.add( entry );

}

 

 

 

////// ToolBinder,这里将重写ViewBinder里面的方法setViewValue,给textview设置onclick事件。这里其实跟重写BaseAapter的做法差不多,都是一样的设置事件。

 

  
    
class ToolBinder implements ViewBinder
{

public boolean setViewValue(View view, Object data, String textRepresentation)
{
ToolNameView tool
= (ToolNameView)view;
ToolboxRow row
= (ToolboxRow)data;

tool.setIntentToLaunch( row.getIntentToLaunch() );
tool.setText( row.getName() );

return true ;
}
}

主要代码:
public class Toolbox extends ListActivity
{
private static final String ACTIVITY_NAME_ENTRY = " activity_name " ;

ArrayList
< HashMap < String, ToolboxRow >> _activityNames;

/* * Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);

setContentView(R.layout.main);

// define the list which holds the information of the list
_activityNames = new ArrayList < HashMap < String, ToolboxRow >> ();

addActivityToList(
" Data Roaming " , new Intent( this , DataRoamingSetting. class ) );
addActivityToList(
" Expanding Example " , new Intent( this , Expando. class ) );

SimpleAdapter toolsAdapter
=
new SimpleAdapter(
this ,
_activityNames,
R.layout.row,
new String[] { ACTIVITY_NAME_ENTRY },
new int [] { R.id.text1 } );

toolsAdapter.setViewBinder(
new ToolBinder() );
setListAdapter( toolsAdapter );
}
}
toolsAdapter.setViewBinder( new ToolBinder() );
这里给SimpleAdapter设置setViewBinder方法,当执行到

  if (binder != null) {

          bound = binder.setViewValue(v, data, text);

  }

会去里面执行,返回true。这样就是完成给item设置监听事件。

你可能感兴趣的:(SimpleAdapter)