本篇内容仅用来记录开发过程,提醒自己。本人目前实习,刚结束安卓三个月,能力有限,如有错误,欢迎指出。
在开发项目过程中,使用Recycler有需求需要在不同情况下显示不同的控件。当时并不知道ViewHolder会被复用,并且只针对不同情况进行控件隐藏,但是并未显示,导致复用该ViewHolder的item的某些控件不显示。在空闲时间自己写了一个Demo进行了验证。
以下是Demo内容
首先写一个最简单的RecycleView例子
MainActivity.java
public class MainActivity extends AppCompatActivity {
@BindView(R.id.rv_demo)
RecyclerView rvDemo;
@BindView(R.id.btn_demo)
Button btnDemo;
private AdapterDemo adapterDemo;
private Set<AdapterDemo.MyViewHoder> viewHoderSet = new HashSet<>();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ButterKnife.bind(this);
List<String> list = new ArrayList<>();
list.add("0");
list.add("1");
list.add("2");
list.add("3");
list.add("4");
list.add("5");
list.add("6");
list.add("7");
list.add("8");
list.add("9");
list.add("10");
list.add("11");
list.add("12");
list.add("13");
list.add("14");
list.add("15");
list.add("16");
list.add("17");
list.add("18");
list.add("19");
list.add("20");
list.add("21");
list.add("22");
adapterDemo = new AdapterDemo(list, this);
rvDemo.setLayoutManager(new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false));
rvDemo.setAdapter(adapterDemo);
}
@OnClick(R.id.btn_demo)
public void showViewHolder(){
Iterator<AdapterDemo.MyViewHoder> iterator = viewHoderSet.iterator();
Log.i("个数", "viewHolder " + viewHoderSet.size());
while (iterator.hasNext()){
Log.i("viewHolder", iterator.next().toString());
}
}
public class AdapterDemo extends RecyclerView.Adapter<AdapterDemo.MyViewHoder> {
private List<String> demoList;
private Context mContext;
public AdapterDemo(List<String> demoList, Context mContext) {
this.demoList = demoList;
this.mContext = mContext;
}
@Override
public MyViewHoder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(mContext).inflate(R.layout.adapter_item, parent, false);
return new MyViewHoder(v);
}
@Override
public void onBindViewHolder(MyViewHoder holder, int position) {
Log.e("测试", holder.toString() + " -- " + position);
viewHoderSet.add(holder);
if (position % 5 == 0)
holder.tv_demo.setVisibility(View.GONE);
else
holder.tv_demo.setText(demoList.get(position));
}
@Override
public int getItemCount() {
return demoList.size();
}
class MyViewHoder extends RecyclerView.ViewHolder {
ImageView iv_demo;
TextView tv_demo;
public MyViewHoder(View itemView) {
super(itemView);
iv_demo = itemView.findViewById(R.id.iv_demo);
tv_demo = itemView.findViewById(R.id.tv_demo);
}
}
}
}
MainActivity布局
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.qxb_810.myapplication.MainActivity"
android:orientation="vertical">
<Button
android:text="打印viewHolder"
android:id="@+id/btn_demo"
android:layout_width="wrap_content"
android:layout_height="40dp"
android:layout_marginBottom="20dp"/>
<android.support.v7.widget.RecyclerView
android:id="@+id/rv_demo"
android:layout_width="match_parent"
android:layout_height="wrap_content"></android.support.v7.widget.RecyclerView>
</LinearLayout>
RecycleView item 布局
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
>
<ImageView
android:id="@+id/iv_demo"
android:layout_width="60dp"
android:layout_height="60dp"
android:background="@color/colorAccent"/>
<TextView
android:id="@+id/tv_demo"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="60sp"
android:text="555555"/>
</LinearLayout>
实现的功能很简单,就是在页面上显示如下图的页面,其中把position是5的倍数的ViewHolder的tv_Demo 控件隐藏掉。按钮的功能是为了能清除的看到生成了几个ViewHolder。效果如图
打印的Log:
目前为止一切正常,可以看到确实position为5的倍数的ViewHolder的TextView确实被隐藏掉了。然后向下滑动到最底层。
效果如图:
这里发现了postion为17和22的TextView也不见了,查看一下Log
发现第17和第22的ViewHolder是复用第0个和第5个的ViewHolder,而在代码处理中,第0个和第5个的ViewHolder中的TextView我们给隐藏掉了。
关键代码如下:
当执行到postion = 17 的时候,判断一下postion不是5的倍数,执行赋值操作,但是这个ViewHolder在postion等于5的时候TextView被隐藏了,而且这里并没有在赋值操作时设置TextView可见,导致虽然赋值了,但是不可见也没用。想要改正也很简单,加一句可见语句就行。
另外在打印ViewHolder生成个数的时候发现总共生成了12个ViewHolder,然而我们又23个item。(不同设备生成的可能不一样,我这里用PAD生成12个,用手机生成10个,另外如果加上可见语句则PAD生成11个)
因为这个问题导致在项目开发时利用RecycleView展示的时候数据时有时无,头疼了好几天,特地记录一下。RecyclerView为了性能考虑复用无可厚非,所以打算并且抽时间深度研究一下RecyclerView的复用机制。