Android(安卓)MVP模式实践
16lz
2021-01-25
前段时间做项目时有用到一个比较常用的设计模式-MVP模式,我个人比较喜欢有优美的结构的代码,我始终相信代码也是一种艺术,现在就特地将这一部分拿出来分享哈,自己也可以再熟悉熟悉。
OK,废话不多说先上个图,来看看我的代码中MVP模式的应用:
- View 代表的是Android中对应的Activity,Fragment或View等与UI相关的。(view通常含有Presenter的引用)
- ViewInterface 用来提取一些可重用的功能,比如Pregress等以及方便的更改View,类之间更加的模块化。使用时,只需要让View去实现这个接口.
- Presenter 相当于一个路由,又来自View的转发请求,以及Model回调的数据实体。(Presenter持有Model层的应用,以及ViewInterface的引用)
Model 业务逻辑层。提取数据从Database,或云端API,缓存等,然后再对数据加以处理,再分发给Presenter去处理。
OK,来个栗子看看。一个根据图书的isbn,从豆瓣的RestFul API中提取图书的细节信息,再返回给前台界面。
1.在View层中
/** * ViewInterface * 定义一些通用的view接口 */public interface LoadDataView { /*** * 耗时操作,加载数据,显示Progress */ void showLoading(); /*** * 隐藏Progress */ void hideLoading();}
/** * 更细小的,用来显示图书细节的View接口 */public interface LoadBookView extends LoadDataView { void showDetailsView(BookEntity entity);}
/*** * Fragment,属于View层,实现了ViewInterface(LoadBookView) */public class BookDetailFragment extends Fragment implements LoadBookView{ /**图书条形码ISBN号*/ public static final String ISBN = "9787121060748"; /**持Presenter对象*/ private BookDetailsPresenter presenter; @Override public void onActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); initWidget(); presenter = new BookDetailsPresenter(getActivity(), ISBN); // 实例化一个presenter对象 presenter.setView(this); //让Presenter持一个ViewInterface实例(LoadBookView) presenter.loadData(); //告诉Presenter快给我加载Data } @Override public void showDetailsView(BookEntity entity) { //更新UI等操作 } @Override public void showLoading() { rlProgress.setVisibility(View.VISIBLE); } @Override public void hideLoading() { rlProgress.setVisibility(View.GONE); }}
2.在Presenter层中
public class BookDetailsPresenter { /**持一个Model层的对象,用来从网页接口Rest Api中提取数据*/ private RestApi restApi = null; /**一个ViewInterface对象,用来回调Data给View*/ private LoadBookView loadBookView; private String isbn; public BookDetailsPresenter(Context context, String isbn) { restApi = new RestApiImpl(context); this.isbn =isbn; } public void setView(LoadBookView loadBookView) { this.loadBookView = loadBookView; } public void loadData() { loadBookView.showLoading(); //耗时操作,开个线程异步的加载数据 Thread thread = new Thread(new Runnable() { @Override public void run() { restApi.getBookDetailByIsbn(isbn, bookDetailsCallback); } }); thread.start(); } //匿名内部类,接收bookDetailCallback的回调数据 private RestApi.BookDetailsCallback bookDetailsCallback = new RestApi.BookDetailsCallback() { @Override public void onBookEntityLoaded(BookEntity bookEntity) { notifyDataLoadedSuccessful(bookEntity); BookDetailsPresenter.this.loadBookView.hideLoading(); } @Override public void onError(Exception e) { //异常后的相关处理 } }; /*** * 通知获取数据成功了,赶快通知UI更新吧 */ private void notifyDataLoadedSuccessful(final BookEntity bookEntity) { Handler handler = new Handler(Looper.getMainLooper()); handler.post(new Runnable() { @Override public void run() { BookDetailsPresenter.this.loadBookView.showDetailsView(bookEntity); } }); } }
3.在Model层中
/**** 整个应用程序需要的数据实体类*/public class BookEntity { //一些set,get方法}/** * 一个接口,用来从rest api api获得数据,它的实现在RestApiImpl中 */public interface RestApi { String API_ISBN_BASE_URL = "https://api.douban.com/v2/book/isbn/"; /*** * 更细小的接口,用来将获取到的数据,回调给它的调用者 */ interface BookDetailsCallback { void onBookEntityLoaded(BookEntity bookEntity); void onError(Exception e); } /** * 从网络获取数据,然后通过bookDetailCallback回调给Presenter * @param isbn * @param bookDetailsCallback */ void getBookDetailByIsbn(final String isbn, final BookDetailsCallback bookDetailsCallback);}
好了核心的代码就贴到这儿了,每个类关键的地方都偶注释,整个Demo的代码在github上,有兴趣可以下来看看。有不好的地方也多多指正,感谢万分!
更多相关文章
- 没有一行代码,「2020 新冠肺炎记忆」这个项目却登上了 GitHub 中
- “罗永浩抖音首秀”销售数据的可视化大屏是怎么做出来的呢?
- Nginx系列教程(三)| 一文带你读懂Nginx的负载均衡
- 不吹不黑!GitHub 上帮助人们学习编码的 12 个资源,错过血亏...
- Android(安卓)定位服务
- Android(安卓)万能适配器 节省你的开发时间
- Android(安卓)应用程序启动过程分析 (用SysTrace 跟踪分析)
- Android自动接听和挂断电话实现原理
- Android实现应用程序卸载自己