个人主页为 The_D的博客
很多人使用 Listview 时,总是用 ViewHolder 的模式来创建,而根据 Customizing Android ListView Rows by Subclassing 中说的,ViewHolder 是一种愚笨的方式。在这篇文章中,作者提出了一个新的思路,也就是通过自定义的 Layout 来代替 ViewHolder。
ViewHolder的缺点
- Adapter 的 getView() 函数承担了很多责任
- ViewHolder 类中通常是一些无意义的代码
- view 的 tag 需要转换到正确的 holder 类型
- 违反了封装性,因为 adapter/holder 必须知道 item 内部有什么 view
demo:
动图下面来说说如何实现:
首先,创建item_relative_layout.xml
:
item由头像ImageView
,名字TextView
和描述TextView
构成
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="200dp">
<ImageView
android:id="@+id/iv"
android:layout_width="150dp"
android:layout_height="150dp"
android:scaleType="fitCenter"
android:layout_centerVertical="true"
android:layout_marginLeft="10dp"
/>
<TextView
android:id="@+id/tv_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toRightOf="@id/iv"
android:layout_marginLeft="20dp"
android:layout_marginTop="60dp"
android:textSize="16sp"
/>
<TextView
android:id="@+id/description"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toRightOf="@id/iv"
android:layout_below="@id/tv_title"
android:layout_marginTop="20dp"
android:layout_marginRight="20dp"
android:layout_marginLeft="20dp"
android:textSize="14sp"
/>
</RelativeLayout>
然后,创建CustomRelativeLayout.java
:
public class CustomRelativeLayout extends RelativeLayout {
//使用ButterKnife注解的方式,简化了findViewById
@Bind(R.id.iv)
ImageView mIv;
@Bind(R.id.tv_title)
TextView mTvTitle;
@Bind(R.id.description)
TextView mDescription;
public CustomRelativeLayout(Context context) {
super(context);
init(context);
}
private void init(Context context) {
LayoutInflater.from(context).inflate(R.layout.item_relative_layout, this);
ButterKnife.bind(this);
//因为每一个item的listener都相同,所以将clickListener写在这个类中,如果不同,可写在adapter的getView()中根据position设置不同listener
setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(getContext(), mTvTitle.getText().toString() + " " + mDescription.getText().toString(), Toast.LENGTH_SHORT).show();
}
});
}
public void setData(int iv, String title, String description){
mIv.setImageResource(iv);
mTvTitle.setText(title);
mDescription.setText(description);
}
}
ListAdapter.java
:
public class ListAdapter extends BaseAdapter {
Context mContext;
int[] images;
String[] titles;
String[] descriptions;
public ListAdapter(Context context) {
mContext = context;
}
public void setData(int[] images, String[] titles, String[] descriptions) {
this.images = images;
this.titles = titles;
this.descriptions = descriptions;
}
@Override
public int getCount() {
return images.length;
}
@Override
public Object getItem(int position) {
return null;
}
@Override
public long getItemId(int position) {
return position;
}
//相对于ViewHolder简化了getView
@Override
public View getView(int position, View convertView, ViewGroup parent) {
CustomRelativeLayout customRelativeLayout = null;
if (convertView != null && convertView instanceof CustomRelativeLayout) {
customRelativeLayout = (CustomRelativeLayout) convertView;
} else {
customRelativeLayout = new CustomRelativeLayout(mContext);
}
customRelativeLayout.setData(images[position], titles[position], descriptions[position]);
return customRelativeLayout;
}
}
UsingCustomLayoutActivity.java
:
public class UsingCustomLayoutActivity extends AppCompatActivity {
@Bind(R.id.lv)
ListView mLv;
ListAdapter mListAdapter;
int[] images = {R.drawable.p1, R.drawable.p2, R.drawable.p3};
String[] titles = {"The_D", "闫一彪", "Android技术小铺"};
String[] descriptions = {"Android开发", "Java后端开发", "我的微信公众号,专注于Android技术分享,欢迎关注"};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_using_custom_layout);
ButterKnife.bind(this);
mListAdapter = new ListAdapter(this);
mListAdapter.setData(images, titles, descriptions);
mLv.setAdapter(mListAdapter);
}
}
activity_using_custom_layout.xml
:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.zhangkaiyue.jkdemo.UsingCustomLayoutActivity">
<ListView
android:id="@+id/lv"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
</RelativeLayout>
这种做法的优势:
这样写可以使item复用,并且针对复杂的Adapter,大大的简化了书写。对于一些跟View相关的逻辑,可以直接写在CustomRelativeLayout中,消除了Adapter的冗余。
我的微信公众号
网友评论