无需设置viewholder的Listview写法

来源:互联网 发布:手机淘宝店收藏链接 编辑:程序博客网 时间:2024/06/02 03:21

原文见

http://www.bignerdranch.com/blog/customizing-android-listview-rows-subclassing/

原文作者不喜欢ViewHolder的原因

    I don’t like this pattern, for several reasons:

    • It puts too much responsibility in the Adapter’s getView(...) method.

    • The “holder” class is typically just boilerplate code and creating it/setting it up is a chore.

    • The view’s tag property requires casting to the correct holder type, which feels kludgy.

    • It violates encapsulation, since the adapter/holder has to know about the internals of the view representing each item in the list.

1:Viewholder在getView里面做了太多工作

2:holder只是样板代码并且写这种代码是令人讨厌的琐事

3:获取tag里面的holder需要强转

4:有违封装性,因为adpater/holder需要知道设置每个item数据的view 的内部结构


无需ViewHolder的写法

先看看Demo截图
custom listview

1. 定义一个Item类来定义列表数据。

   public class Item {        private String mImageUrl;        private String mTitle;        private String mDescription;        // constructor, getters and setters elided    }

2. 定义itemview的布局。

<com.bignerdranch.android.listitemviewdemo.ItemView        xmlns:android="http://schemas.android.com/apk/res/android"        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:padding="5dp" />

3.定义你自己的布局(子View)

 <?xml version="1.0" encoding="utf-8"?>    <merge      xmlns:android="http://schemas.android.com/apk/res/android"      android:layout_width="match_parent"      android:layout_height="wrap_content" >      <ImageView        android:id="@+id/item_imageView"        android:background="@android:color/darker_gray"        android:layout_width="60dp"        android:layout_height="60dp"        android:layout_margin="5dp"        android:contentDescription="@string/item_imageView_contentDescription"        />      <TextView        android:id="@+id/item_titleTextView"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:layout_toRightOf="@id/item_imageView"        android:text="title text"        />      <TextView        android:id="@+id/item_descriptionTextView"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:layout_toRightOf="@id/item_imageView"        android:layout_below="@id/item_titleTextView"        android:layout_marginTop="5dp"        android:text="description text"        />    </merge>

4. 自定义ItemView类

具体步骤:

1:通过ItemView的inflate方法获取ItemView

2: ItemView创建时调用构造方法初始化子View(你的布局)绑定起来,并且调用SetupChildren()获取子View控件存储在ItemView中

代码:

public class ItemView extends RelativeLayout {    private TextView mTitleTextView;    private TextView mDescriptionTextView;    private ImageView mImageView;    public static ItemView inflate(ViewGroup parent) {        ItemView itemView = (ItemView)LayoutInflater.from(parent.getContext())                .inflate(R.layout.item_view, parent, false);        return itemView;    }    public ItemView(Context c) {        this(c, null);    }    public ItemView(Context context, AttributeSet attrs) {        this(context, attrs, 0);    }    public ItemView(Context context, AttributeSet attrs, int defStyle) {        super(context, attrs, defStyle);        LayoutInflater.from(context).inflate(R.layout.item_view_children, this, true);        setupChildren();    }    private void setupChildren() {        mTitleTextView = (TextView) findViewById(R.id.item_titleTextView);        mDescriptionTextView = (TextView) findViewById(R.id.item_descriptionTextView);        mImageView = (ImageView) findViewById(R.id.item_imageView);    }    public void setItem(Item item) {        mTitleTextView.setText(item.getTitle());        mDescriptionTextView.setText(item.getDescription());        // TODO: set up image URL    }        public ImageView getImageView () {        return mImageView;    }    public TextView getTitleTextView() {        return mTitleTextView;    }    public TextView getDescriptionTextView() {        return mDescriptionTextView;    }}

5. 创建ListView用的adapter类(ItemAdapter)。

具体步骤:

 1.adapter使用ItemView静态方法Inflter()获得ItemView对象,

2.ItemView调用setItem(item)把数据设置到ItemView里面的子View控件上

        public ItemAdapter(Context c, List<Item> items) {        super(c, 0, items);    }        @Override    public View getView(int position, View convertView, ViewGroup parent) {        ItemView itemView = (ItemView)convertView;        if (null == itemView)            itemView = ItemView.inflate(parent);        itemView.setItem(getItem(position));        return itemView;    }}

6. 剩下的就是在activity获取和设置ListView了。

总结这种写法的优势

  • The Adapter implementation is greatly simplified.

  • The ItemView can be created easily in code or in an XML layout file.

  • Any future customizations or configuration-specific changes to the layout of ItemView can be handled entirely within that class’ implementation and layout files.

  • There are no extra “holder” classes or objects created during the process.


  • Adapter的代码会变得极其简洁
  • 很容易通过代码和xml文件来创建ItemView
  • 以后有需要更改,只需要对布局文件和ItemView进行动刀即可
  • 整个过程无需创建额外的holder类和对象

好了,基本就这样,转述可能跟原文有些出入,有能力的话可以看原文怎么说明的。





0 0
原创粉丝点击