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

来源:互联网 发布:淘宝充值流量如何退款 编辑:程序博客网 时间:2024/04/28 07:11

如题,这里主要讲解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设置监听事件。

 

 

原创粉丝点击