0%

recyclerView使用小结(一)

recyclerView.Adapter主要方法及执行顺序

  • recyclerview适配器Adapter中主要方法有构造方法、onCreateViewHolder、onBindViewHolder、getItemViewType、getItemCount五个主要方法;

  • 主要的方法的执行顺序为:构造方法 –> getItemViewType –> onCreateViewHolder –> onBindViewHolder

在同一个recyclerView中显示不同有UI并且每类UI的数据结构也不同

针对不同的数据结构,先创建数据的基类IBaseData,定义不的类型常量如TYPE_FIRST=1及默认类型TYPE_NULL=-1,对外暴露获取类型的方法与获取数据T的方法;

1
2
3
4
5
6
7
8
9
10
11
12
public interface IBaseData<T> {

public static final int TYPE_NULL = -1;
public static final int TYPE_FIRST = 1;
public static final int TYPE_SECOND = 2;

void setEntity(T data);

T getEntity();

int getType();
}

新建类BaseDataImpl实现之前创建的数据基类IBaseData,通过构造方法传不同的数据类型的实例bean;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
public class BaseDataImpl implements IBaseData {

protected Object object;
protected int type;

public BaseDataImpl(Object object, int type) {
this.object = object;
this.type = type;
}

@Override
public void setEntity(Object data) {
this.object = data;
}

@Override
public Object getEntity() {
return object;
}

@Override
public int getType() {
return type;
}
}

针对不同的UI类型,创建所有viewHolder的基类BaseViewHolder,传入布局layoutId,统一创建当前类型的界面,再由不同子类通过findViewById去查找使用子控件;关键方法是bindViewHolder(IBaseData data, int position)来调用adapter的根方法onBindViewHolder(BaseViewHolder holder, int position),这样就实现了不同界面的viewHolder处理不同界面的数据,各自不干扰;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public abstract class BaseViewHolder extends RecyclerView.ViewHolder {

public BaseViewHolder(ViewGroup parent, int layoutId) {
super(inflateView(parent,layoutId));
}

private static View inflateView(ViewGroup parent, int layoutId) {
return LayoutInflater.from(parent.getContext()).inflate(layoutId, parent, false);
}

protected View findViewById(int viewId){
return itemView.findViewById(viewId);
}

protected abstract void bindViewHolder(IBaseData data, int position);
}

新建recyclerView的adapter类MyAdapter,实现构造方法、onCreateViewHolder、onBindViewHolder、getItemViewType、getItemCount五个主要方法,adapter类以List<BaseDataImpl>界面数据集合,根据BaseDataImpl的不同type来创建和绑定不同的viewHolder;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
public class MyAdapter extends RecyclerView.Adapter<BaseViewHolder> {

private List<BaseDataImpl> mData;

public MyAdapter(List<BaseDataImpl> mData) {
this.mData = mData;
}

public void setData(List<BaseDataImpl> data) {
this.mData = data;
}

@NonNull
@Override
public BaseViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
if (IBaseData.TYPE_FIRST == viewType) {
return new LeftTextViewHolder(parent, R.layout.item_left_text);
} else if (IBaseData.TYPE_SECOND == viewType) {
return new RightTextViewHolder(parent, R.layout.item_right_text);
} else {
return null;
}
}

@Override
public void onBindViewHolder(BaseViewHolder holder, int position) {
holder.bindViewHolder(mData.get(position), position);
}

@Override
public int getItemViewType(int position) {
return mData.get(position) == null ? IBaseData.TYPE_NULL: mData.get(position).getType();
}

@Override
public int getItemCount() {
return mData == null? 0: mData.size();
}
}

其中LeftTextViewHolderBaseViewHolder的实现类,对应的数据结构LeftData与界面布局item_left_text如下,RightDataLeftData数据结构一样,item_right_text布局靠右对齐,item_left_text靠左对齐;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
public class LeftData {

private String title;
private String subTitle;

public LeftData(String title, String subTitle) {
this.title = title;
this.subTitle = subTitle;
}

public String getTitle() {
return title;
}

public void setTitle(String title) {
this.title = title;
}

public String getSubTitle() {
return subTitle;
}

public void setSubTitle(String subTitle) {
this.subTitle = subTitle;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content">

<TextView
android:id="@+id/tv_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:layout_marginLeft="15dp"
android:paddingTop="15dp"
android:text="我是标题"
android:textColor="#000000"
android:textSize="16sp" />

<TextView
android:id="@+id/tv_subTitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/tv_title"
android:layout_marginLeft="15dp"
android:layout_marginTop="8dp"
android:paddingBottom="15dp"
android:text="我是子标题"
android:textColor="#99000000"
android:textSize="12sp" />
</RelativeLayout>

在界面类RecyclerViewActivity中引中新建的adapter类,并传入不同类型的数据,如LeftData封装进BaseDataImpl统一由MyAdapter处理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
public class RecyclerViewActivity extends AppCompatActivity {

@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_recyclerview);

RecyclerView rvContent = (RecyclerView) findViewById(R.id.rv_content);
rvContent.setLayoutManager(new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false));

LeftData leftData = new LeftData("我是主标题我是主标题","我是小标题我是小标题我是小标题");
BaseDataImpl leftImpl = new BaseDataImpl(leftData, IBaseData.TYPE_FIRST);

RightData rightData = new RightData("我是主标题我是主标题","我是小标题我是小标题我是小标题");
BaseDataImpl rightImpl = new BaseDataImpl(rightData, IBaseData.TYPE_SECOND);

List<BaseDataImpl> dataList = new ArrayList<>();
dataList.add(leftImpl);
dataList.add(rightImpl);

MyAdapter myAdapter = new MyAdapter(dataList);
rvContent.setAdapter(myAdapter);

}
}

界面显示效果如下,这样就实现了在同一个recyclerView中显示不同样式的布局。

2021-01-26-121132