简单示例演示如何从自由写法改进到MVC再改进到MVP - 4 - MVP2
上一篇: https://www.jianshu.com/p/aabe77839655 - 3 - MVP,MVP的写法
另一种MVP2是啥样?
这个模式我还真没找到相关的图,那就描述一下吧!
上一篇中MVP的设计图是这样的:
MVP.png
这个MVP2跟他类似,但有两个区别:
一个区别是在于上一篇中提到的:
这(上)个MVP实现中,还是直接用Fragment实现了IView接口
另外一个区别是:
View不直接引用Presenter,而是通过接口
这个设计中Fragment作为中介,实现了IView和IPresenter中的回调接口。
先看Fragment和IView的分离:
简单的说就是在Fragment的onCreateView
方法中返回一个View,而这个View实现了IView接口。
我们先看下IView::
public interface IBaseView {
View getRootView();
Context getContext();
}
IBaseView
是一个基础接口,具体的页面应该有自己的一个IView,比如:
public interface IUserListView extends IBaseView {
interface IListViewHandler {
void onRefreshList(); // 重点:注意这个是连接View 和 Presenter的接口方法
}
void updateList(List<UserModel> userModels);
void showLoading();
void hideLoading();
void setViewHandler(IListViewHandler handler);
void setEmptyListText(String emptyListViewTextString);
}
而这个IUserListView
的实现类是这样的:
public class UserListView implements IUserListView {
private ScrollChildSwipeRefreshLayout mRefreshLayout;
private ListView mUserListView;
private UserListAdapter mUserListAdapter;
private IListViewHandler mListViewHandler; // 重点:没有引用 Presenter,而是实现了一个回调接口
private View mEmptyView;
private TextView mEmptyTextView;
private View mRootView;
private Context mContext;
public UserListView(LayoutInflater layoutInflater, ViewGroup container) {
mRootView = layoutInflater.inflate(getLayoutId(), container, false);
mContext = mRootView.getContext();
init(mRootView);
}
private int getLayoutId() {
return R.layout.fragment_list;
}
protected void init(View rootView) {
mRefreshLayout = rootView.findViewById(R.id.refresh_layout);
mUserListView = rootView.findViewById(R.id.user_list_view);
mUserListAdapter = new UserListAdapter(null);
mUserListView.setAdapter(mUserListAdapter);
mRefreshLayout.setScrollUpChild(mUserListView);
mRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
@Override
public void onRefresh() {
if (mListViewHandler != null) {
mListViewHandler.onRefreshList();
}
}
});
mEmptyView = rootView.findViewById(R.id.empty_list_layout);
mEmptyTextView = mEmptyView.findViewById(R.id.empty_list_text_view);
}
@Override
public void updateList(List<UserModel> userModels) {
hideLoading();
mUserListAdapter.setUserModelList(userModels);
mUserListAdapter.notifyDataSetChanged();
Toast.makeText(getContext(), "Update UI", Toast.LENGTH_LONG).show();
}
@Override
public void showLoading() {
mRefreshLayout.setRefreshing(true);
}
@Override
public void hideLoading() {
mRefreshLayout.setRefreshing(false);
}
@Override
public void setViewHandler(IListViewHandler handler) {
mListViewHandler = handler;
}
@Override
public void setEmptyListText(String emptyListViewTextString) {
String emptyText = mContext.getResources().getString(R.string.empty_text, emptyListViewTextString);
mEmptyTextView.setText(emptyText);
mUserListView.setEmptyView(mEmptyView);
}
@Override
public View getRootView() {
return mRootView;
}
@Override
public Context getContext() {
if (mRootView == null) {
return null;
}
return mRootView.getContext();
}
}
再看Fragment的实现,一切都就清楚了。
- Fragment中实现了
IListViewHandler
和ListUpdaterListener
, 他们分别是IView 和 IPresenter 的回调。 - 当用户操作(比如下拉)时调用
IListViewHandler
的回调方法,此时执行到Fragment
里面的代码, - 在
Fragment
里面调用Presenter
的方法执行数据交互 - 然后
Presenter
调用ListUpdaterListener
的方法触发到Fragment
里面的回调 -
Fragment
再调用IView
的方法来完成UI更新
这几步完成了IView和IPresenter的解耦。
public class MVP2UserListFragment extends Fragment implements IUserListView.IListViewHandler,
UserListPresenter.ListUpdaterListener, IMainPresenter.IFabListener {
private IUserListView mListView;
IUserListPresenter mPresenter;
public MVP2UserListFragment() {
super();
}
public static MVP2UserListFragment newInstance() {
return new MVP2UserListFragment();
}
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mPresenter = new UserListPresenter();
}
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
mListView = new UserListView(inflater, container);
mListView.setViewHandler(this);
mListView.setEmptyListText(mPresenter.getEmptyListText());
return mListView.getRootView();
}
@Override
public void onResume() {
super.onResume();
mPresenter.registerListener(this);
}
@Override
public void onPause() {
super.onPause();
mPresenter.unregisterListener(this);
}
@Override
public void onRefreshList() {
mListView.showLoading();
mPresenter.loadList();
}
@Override
public void updateList(List<UserModel> userModels) {
mListView.hideLoading();
mListView.updateList(userModels);
}
@Override
public void onFabClicked() {
mListView.showLoading();
mPresenter.addUser();
}
}
贴下IPresenter
:
public interface IUserListPresenter<T> extends IBasePresenter<T> {
void loadList();
void addUser();
String getEmptyListText();
}
和Presenter
public class UserListPresenter extends BasePresenter<UserListPresenter.ListUpdaterListener> implements IUserListPresenter<UserListPresenter.ListUpdaterListener> {
private List<UserModel> mUserModels;
public UserListPresenter() {
}
public void loadList() {
BackgroundThreadPoster.post(new Runnable() {
@Override
public void run() {
mUserModels = UserManager.callAPIToGetUserList();
updateUI(mUserModels);
}
});
}
public void addUser() {
BackgroundThreadPoster.post(new Runnable() {
@Override
public void run() {
UserModel userModel = UserManager.addUser();
mUserModels.add(userModel);
updateUI(mUserModels);
}
});
}
@Override
public String getEmptyListText() {
return "MVP2 :: ";
}
private void updateUI(final List<UserModel> userModels) {
MainThreadPoster.post(new Runnable() {
@Override
public void run() {
for (ListUpdaterListener listener : getListeners()) {
listener.updateList(userModels);
}
}
});
}
public interface ListUpdaterListener {
void updateList(List<UserModel> userModels);
}
}
网友评论