您的位置:首页 > 移动开发 > Android开发

Android RecyclerView中实现ChecckBox单选的正确方式

2016-12-05 12:04 661 查看
以前使用recyclerView时,如果item中有单选框需要选中,一般的实现方式是创建一个boolean类型的ArrayList用来存储列表中每个item的checkBox是否选中,设置一个标志位mCurrentPosition来记录当前被选中的checkBox的item的position,然后在每次点击item时,设置ArrayList的list中mCurrentPosition(也就是上一次选中的item)的值为false,设置list中当前position的boolean为true,设置mCurrentPosition为当前position,然后再调用Adapter.notifyDatasetChanged()方法刷新recyclerView。

这种方式缺点一是需要创建一个ArrayList的列表数组,占内存。如果recyclerView的数据源数据量很大,那么就会造成更大的内存存储开销,浪费了手机上宝贵的内存资源。缺点二是调用了notifyDataSetChanged方法后会刷新当前recyclerView中所有可见的item,也就是会重新调用onBindViewHolder这个方法来重新刷新item,会造成图片闪烁,虽然只是刷新当前可见的item,数量不多,对性能来说影响不大,但我们还是要保持对性能优化的极致的追求,最好的做法就是只刷新当前2个item就可以了,下面介绍一下怎么正确实现recyclerView中的单选。

效果图:



主要是Adapter的实现:

public class ContactSelectAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private List<AVUser> mList;//数据源
private Context mContext;//context上下文
private LayoutInflater mInflater;//布局解析器 用来解析布局生成View的
private int mSelectedPos=-1;//保存当前选中的position 重点!

//构造函数,传入context和与当前adapter绑定的recyclerView
public ContactSelectAdapter(Context context){
this.mContext=context;
this.mInflater=LayoutInflater.from(mContext);
mList=new ArrayList<>();//防止为设置数据源时为空
}

//设置数据源
public void setDataSource(List<AVUser> list){
this.mList=list;
}

//创建ViewHolder
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
ContactHolder holder=new ContactHolder(mInflater.inflate(R.layout.contact_select_recyclerview_item,parent,false));
return holder;
}

@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
//不使用 使用3个参数的重载函数
}

//绑定ViewHolder中的资源 使用三个参数的onBindViewHolder
@Override
public void onBindViewHolder(final RecyclerView.ViewHolder holder, final int position,List payloads) {
final ContactHolder contact= (ContactHolder) holder;
if(payloads.isEmpty()){//payloads即有效负载,当首次加载或调用notifyDatasetChanged() ,notifyItemChange(int position)进行刷新时,payloads为empty 即空
AVUser user=mList.get(position);
contact.userName.setText(user.getString("name"));
contact.userId.setText(String.format("工号ID:%d",user.getInt("employeeId")));
AVFile img=user.getAVFile("portrait");
Glide.with(mContext).load(img.getUrl())
.centerCrop()
.transform(new GlideCircleTransform(mContext))
.dontAnimate()
.placeholder(R.drawable.dayhr_userphoto_def)
.into(contact.userImg);
contact.checkBox.setChecked(mSelectedPos==position);
}else{//当调用notifyItemChange(int position, Object payload)进行布局刷新时,payloads不会empty ,所以真正的布局刷新应该在这里实现 重点!
contact.checkBox.setChecked(mSelectedPos==position);
}

holder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if(mSelectedPos!=position){//当前选中的position和上次选中不是同一个position 执行
contact.checkBox.setChecked(true);
if(mSelectedPos!=-1){//判断是否有效 -1是初始值 即无效 第二个参数是Object 随便传个int 这里只是起个标志位
notifyItemChanged(mSelectedPos,0);
}
mSelectedPos=position;
}
}
});
}

//提供给外部Activity来获取当前checkBox选中的item,这样就不用去遍历了 重点!
public int getSelectedPos(){
return mSelectedPos;
}

@Override
public int getItemCount() {
return mList.size();
}

public class ContactHolder extends RecyclerView.ViewHolder{
public CheckBox checkBox;//单选框 重点!
public TextView userName;
public TextView userId;
public ImageView userImg;

public ContactHolder(View itemView) {
super(itemView);
checkBox= (CheckBox) itemView.findViewById(R.id.ContactSelect_list_item_checkBox);
userName= (TextView) itemView.findViewById(R.id.ContactSelect_list_item_user_name);
userId= (TextView) itemView.findViewById(R.id.ContactSelect_list_item_user_employeeId);
userImg= (ImageView) itemView.findViewById(R.id.ContactSelect_list_item_img);
}
}


Activity:

mRecyclerView= (RecyclerView) findViewById(R.id.ContactSelectActivity_recyclerView);
mRecyclerView.setLayoutManager(new LinearLayoutManager(this));//设置布局管理器 为线性布局
mRecyclerView.addItemDecoration(new DividerItemDecoration(this,DividerItemDecoration.VERTICAL_LIST));//设置分割线
mAdapter=new ContactSelectAdapter(this);
mRecyclerView.setAdapter(mAdapter);
mAdapter.setDataSource(list);
mAdapter.notifyDataSetChanged();


布局文件:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:background="@android:color/white"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingLeft="20dp"
android:paddingTop="10dp"
android:paddingBottom="10dp"
android:paddingRight="20dp"
>

<CheckBox
android:id="@+id/ContactSelect_list_item_checkBox"
android:layout_width="20dp"
android:layout_height="20dp"
android:layout_centerVertical="true"
android:button="@null"
android:enabled="false"
android:background="@drawable/contact_select_list_item_checkbox_bg"/>

<ImageView
android:id="@+id/ContactSelect_list_item_img"
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_toRightOf="@id/ContactSelect_list_item_checkBox"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:layout_centerVertical="true"
android:src="@drawable/dayhr_userphoto_def"/>

<LinearLayout
android:orientation="vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_toRightOf="@id/ContactSelect_list_item_img">

<TextView
android:id="@+id/ContactSelect_list_item_user_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="@android:color/black"
android:text="马云"
android:textSize="16sp" />

<TextView
android:id="@+id/ContactSelect_list_item_user_employeeId"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="工号:1008"
/>

</LinearLayout>
</RelativeLayout>


最重点的还是RecyclerView中的onBindViewHolder的三个参数的方法

public void onBindViewHolder(final RecyclerView.ViewHolder holder, final int position,List payloads)

和notifyItemChanged的两个参数的方法

public final void notifyItemChanged(int position, Object payload)

接下来分析这两个方法的介绍 详情见下一章博客

http://blog.csdn.net/qq402164452/article/details/53464091
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: