简介
本文介绍了Adapter在MVP模式中的使用方式 首先Adapter主要是用作数据展示的作用,通常在Fragment或者Activity中嵌套使用。
尝试
我在参考了一些资料后做出如下尝试,这里以联系人列表为例子。
- adapter接收P层,viewHolder作为V层,通过onBindViewHolder绑定在一起
- 数据保存在P层并监听数据源的更新
- 在AdapterContract定义要渲染数据的数据格式.按条目渲染Item.
- 将Item的事件控制在P层
- 将ListView的显示等交给它所在父控件。
代码如下:
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
BaseAdapterPresenter.java
public interface BaseAdapterPresenter<T> {
void start();
/**
* 加载数据
*/
void loadData();
/**
* 获取数据个数
*/
int getDataCount();
/**
* 销毁
*/
void onDestroy();
/**
* 获得渲染对象
*
* @param index
* @return
*/
T getItemDraw(int index);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
BaseAdapterView.java
public interface BaseAdapterView<T> {
void onDataUpdate();
/**
* 渲染的Item
*
* @param itemDraw
* @param position
*/
void renderItem(T itemDraw, int position);
}
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
40
41
42
43
ContactsAdapterContract.java
public class ContactsAdapterContract {
/**
* 渲染数据封装对象
*/
public static class ContactItemDraw {
public boolean showSection;
public String section;
public String header;
public String name;
public String number;
public boolean showCloud;
}
public interface View extends BaseAdapterView<ContactItemDraw> {
/***
* 掉起xx界面
*/
void showXXActivity(String args);
}
public interface Presenter extends BaseAdapterPresenter<ContactItemDraw> {
/**
* 跳转至显示联系人详情界面
*
* @param mContext
* @param position
*/
void startContactsDetailsActivity(Context mContext, int position);
void onBindContractsRecyclerView(ContactsAdapterContract.View view, int position);
/**
* 其他事件
*
*/
....
}
}
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
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
public class ContractsAdapterPresenter implements ContactsAdapterContract.Presenter {
private ContactsSync.ContactsWrapper mContactsWrapper;
private ContactsAdapterContract.View mView;
@Subscribe(threadMode = ThreadMode.MAIN)
public void onContactEvent(ContactEvent event) {
switch (event.type) {
case ContactEvent.EVENT_READ_ANDROID_CONTACTS:
loadData();
break;
default:
break;
}
}
@Override
public void loadData() {
mContactsWrapper = ContactsSync.getContactsWrapper();
//todo 数据改变通知上层
}
@Override
public void start() {
EventBus.getDefault().register(this);
loadData();
}
@Override
public void onDestroy() {
EventBus.getDefault().unregister(this);
}
@Override
public ContactsAdapterContract.ContactItemDraw getItemDraw(int index) {
ContactsAdapterContract.ContactItemDraw item = new ContactsAdapterContract.ContactItemDraw();
ContactTool.AndroidContact androidContact = mContactsWrapper.contacts.get(index);
item.header = androidContact.photoUri;
item.name = androidContact.name;
item.number = androidContact.phone;
item.showCloud = false;
return item;
}
return null;
}
@Override
public void startContactsDetailsActivity(Context mContext, int position) {
ContactsDetailsActivity.launch(mContext, getItemDraw(position).number);
}
@Override
public void onBindContractsRecyclerView(ContactsAdapterContract.View view, int position) {
mView = view;
mView.renderItem(getItemDraw(position), position);
}
@Override
public int getDataCount() {
return mContactsWrapper != null ? mContactsWrapper.contacts.size() : 0;
}
}
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
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
public class ContactsRecyclerViewAdapter extends RecyclerView.Adapter<ContactsRecyclerViewAdapter.ViewHolder> {
private ContactsAdapterContract.Presenter mPresenter;
private Context mContext;
public ContactsRecyclerViewAdapter(Context context, ContactsAdapterContract.Presenter presenter) {
mContext = context;
mPresenter = presenter;
mPresenter.start();
}
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.view_contact, parent, false);
return new ViewHolder(view);
}
@Override
public void onBindViewHolder(final ViewHolder holder, int position) {
mPresenter.onBindContractsRecyclerView(holder, position);
}
@Override
public int getItemCount() {
return mPresenter.getDataCount();
}
public class ViewHolder extends RecyclerView.ViewHolder implements ContactsAdapterContract.View {
@BindView(R.id.txt_contact_item_section)
TextView mSection;
@BindView(R.id.txt_contact_item_name)
TextView mName;
@BindView(R.id.txt_contact_item_number)
TextView mNumber;
@BindView(R.id.img_cloud)
ImageView mCloud;
@BindView(R.id.img_avatar)
ImageView mAvatar;
@BindView(R.id.txt_avatar_name)
TextView mAvatarName;
private int mCurrentPosition;
public ViewHolder(View view) {
super(view);
ButterKnife.bind(this, view);
}
@OnClick(R.id.view_avatar)
void onClickHead(View view) {
mPresenter.startContactsDetailsActivity(mContext, mCurrentPosition);
}
@OnClick(R.id.view_contact_item)
void onClickCallItem(View view) {
mPresenter.call(mCurrentPosition);
}
@Override
public void onDataUpdate() {
}
@Override
public void renderItem(ContactsAdapterContract.ContactItemDraw item, int position) {
mCurrentPosition = position;
if (item != null) {
mSection.setVisibility(item.showSection ? View.VISIBLE : View.GONE);
mSection.setText(item.section);
mName.setText(item.name);
mNumber.setText(item.number);
mCloud.setVisibility(item.showCloud ? View.VISIBLE : View.INVISIBLE);
if (item.header != null) {
mAvatarName.setVisibility(View.INVISIBLE);
} else {
mAvatarName.setVisibility(View.VISIBLE);
if (item.name.length() >= 2) {
mAvatarName.setText(item.name.substring(item.name.length() - 2, item.name.length()));
} else {
mAvatarName.setText(item.name);
}
mAvatar.setImageDrawable(CircleDrawables.getDefault());
}
}
}
}
}
分析
经过大佬指点,做出以下结论:
- 将adapter和宿主界面拆分开会导致接口类爆炸。
- adapter功能简单,主要功能就是获取数据和展示数据,抽取后接口不多。
- 事件交给宿主界面处理,将list和宿主作为整体即可,没有必要进行拆分。
- 宿主V层控制Adapter的P层,逻辑错误。
- 不利于平台逻辑代码移植
最终处理方案
将数据层封装到宿主界面的P层,由adapter 自己拿数据渲染。