MVP架構(gòu)最近很是火熱,其實(shí)app架構(gòu)并沒(méi)有好壞之分,只要選擇合適的,都OK的。一般小項(xiàng)目,功能不是很多的,業(yè)務(wù)邏輯寫(xiě)到 Activity 下面并無(wú)太多問(wèn)題,但一旦業(yè)務(wù)逐漸變得復(fù)雜起來(lái),每個(gè)頁(yè)面之間有不同的數(shù)據(jù)交互和業(yè)務(wù)交流時(shí),activity 的代碼就會(huì)急劇膨脹,代碼就會(huì)變得可讀性,維護(hù)性很差,此時(shí)我們就可以考慮使用MVP架構(gòu)。一般小公司app,其實(shí)都沒(méi)必要使用MVP,個(gè)人淺見(jiàn)。當(dāng)然MVP好處多多,層次清晰,易于測(cè)試,Activity代碼更顯精煉。這里,筆者使用豆瓣的API來(lái)演示一下MVP架構(gòu)。
MVP,顧名思義:
View 對(duì)應(yīng)于Activity,fragment,負(fù)責(zé)View的繪制以及與用戶交互
Model 依然是業(yè)務(wù)邏輯和實(shí)體模型
Presenter 負(fù)責(zé)完成View于Model間的交互
圖中所示,Model和View互不相干,靠Presenter維系交互。
以豆瓣讀書(shū)搜索為例,首先分析下View層,需要下拉刷新,加載更多,加載提示,顯示信息等功能,那么View代碼可以寫(xiě)成如下:
public interface BookView {
void showLoading(String msg);
void hideLoading();
void refreshListData(List<Book> items);
void addMoreListData(List<Book> items);
void showMessage(String message);
}
再看P層代碼
public interface BookPresenter {
void loadListData(String q, int start, int count);
void onItemClickListener(int position);
}
private Context mContext;
private BookView bookView;
private BookListInteractorImpl bookListInteractor;
public BookPresenterImpl(Context context,BookView bookView){
this.mContext = context;
this.bookView = bookView;
bookListInteractor = new BookListInteractorImpl(this);
}
@Override
public void loadListData(String q, int start, int count) {
bookListInteractor.getBookList(q,start,count);
}
@Override
public void onItemClickListener(int position) {
}
@Override
public void onSuccess(int tag,List<Book> data) {
if(tag == Common.REFRESH_DATA){
bookView.refreshListData(data);
}else if(tag == Common.LOADMORE_DATA){
bookView.addMoreListData(data);
}
}
@Override
public void onError(String msg) {
bookView.showMessage(msg);
}
@Override
public void onException(String msg) {
bookView.showMessage(msg);
}
}
從代碼中可以看到Presenter持有View層和Model的接口,View負(fù)責(zé)UI顯示,Model層負(fù)責(zé)數(shù)據(jù)獲取,Presenter則負(fù)責(zé)調(diào)度View和Model。這里可以看出,即使設(shè)計(jì)還沒(méi)出UI,我們也可以代碼寫(xiě)起來(lái)。
再看下model層
public interface BookListInteractor { void getBookList(String q,int start,int count);}
在getBookList具體實(shí)現(xiàn)數(shù)據(jù)獲取就OK了。
最后看下Activity
public class BookActivity extends AppCompatActivity implements BookView{
private Toolbar toolbar;
private XRecyclerView rv_list;
private List<Book> bookList = new ArrayList<>();
private BookAdapter adapter;
private BookPresenterImpl bookPresenter;
private int start = 0;
private String key;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
supportRequestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.ac_book_layout);
toolbar = (Toolbar) findViewById(R.id.toolbar);
key = getIntent().getStringExtra("key");
bookPresenter = new BookPresenterImpl(BookActivity.this,this);
rv_list = (XRecyclerView) findViewById(R.id.rv_list);
StaggeredGridLayoutManager manager = new StaggeredGridLayoutManager(2, StaggeredGridLayoutManager.VERTICAL);
SpaceItemDecoration space = new SpaceItemDecoration(12);
rv_list.addItemDecoration(space);
rv_list.setLayoutManager(manager);
adapter = new BookAdapter(this,R.layout.list_item_book,bookList);
rv_list.setAdapter(adapter);
rv_list.setLoadingListener(new XRecyclerView.LoadingListener() {
@Override
public void onRefresh() {
start = 0;
bookPresenter.loadListData(key,start,10);
}
@Override
public void onLoadMore() {
start +=10;
bookPresenter.loadListData(key,start,10);
}
});
bookPresenter.loadListData(key,start,10);
}
@Override
public void showLoading(String msg) {
}
@Override
public void hideLoading() {
}
@Override
public void refreshListData(List<Book> items) {
rv_list.refreshComplete();
bookList.clear();
bookList.addAll(items);
adapter.notifyDataSetChanged();
}
@Override
public void addMoreListData(List<Book> items) {
rv_list.loadMoreComplete();
bookList.addAll(items);
adapter.notifyDataSetChanged();
}
@Override
public void showMessage(String message) {
Toast.makeText(this,message,Toast.LENGTH_SHORT).show();
}
}
Activity實(shí)現(xiàn)了View以及持有Presenter實(shí)例,這樣就妥了!
由此可以見(jiàn)MVP架構(gòu)解決了View層和Model的耦合,大大減少了Activity的代碼,業(yè)務(wù)邏輯與View分離,代碼層次清晰,易于維護(hù)擴(kuò)展。當(dāng)然這里的代碼只是演示MVP的寫(xiě)法,有不妥之處,歡迎吐槽。
本文代碼demo:https://github.com/shuijilove/AndroidMVPDemo
Github上的一些MVP框架:
https://github.com/sockeqwe/mosby
https://github.com/kymjs/TheMVP