caffeine-coffee-cup-6347.jpg
Android 架构蓝图
Android Architecture Blueprints 是 Google 的一个开源项目, 项目使用不同的架构概念和工具实现相同的应用程序, 作为示例用作开发者学习如何构建代码; 同时 Google 也不建议我们将这些示例作为规范示例, 我们应该根据这些概念构建自己项目最适合的架构; 学习项目的时候写一下自己的体会
MVP 架构
使用架构
为什么使用架构呢? 总的来说就是之前的代码写的太乱了; 基本上所有的东西都在 Activity 或者 Fragement 中进行, 导致一个 Activity 里面有太多的东西需要处理; 这种写法其实都谈不上 MVC 架构, 因为数据的获取, 保存也是在 Activity 里面写了; 这个时候 Activity 的代码就显得特别的庞大; 一旦需求变更或出现 bug, 那简直就是噩梦一场
对 MVP 的理解
Android MVP 十分钟入门: https://juejin.im/post/58870cc2128fe1006c46e39c
之前看东西都喜欢简单略过这个东西的概念然后去看具体的实现; 这个其实是有问题的, 比如之前看 MVP 架构也是一样, 直接看别人是怎么实现的, 额, 首先新建三个文件夹, 一个放 Model, 一个放 View, 一个放 Presenter, 然后照着样子写写, 的确像那么回事, 但是再看另一个 MVP 项目就感觉好像和自己写的不一样了; 其实就是没有好好理解 MVP 的概念, 思想, MVP 并没有一个固定的写法, 只是一种概念, 每个人, 每个项目有不同的写法; 只有先了解它的概念, 思想, 在使用中有疑惑的时候, 按照这种思想来继续构建项目;
MVP 其实就是将项目分为了三层
Model 层: 负责操纵数据, 存取, 增删改查
View 层: 负责界面展示和交互
Presenter: 连接 View 层与 Model 层的桥梁并对业务逻辑进行处理; Model 去获取数据, 本地或者网络, 解析回来, 通过 View 接口提供给界面显示
对于 P 层网上更多是没有写对业务逻辑进行处理这点, 比如说 Google MVP 的 demo 里, 获取数据的时候有在 P 层对数据进行过滤的处理; 这个操作其实在 M 层也可以做, 那按照 MVP 架构就在 P 层进行处理;
使用栗子
Google 的 MVP 项目是一个记事本的栗子, 我自己也新建了一个项目简单的相册的功能; 功能就是可以从本地选取图片放到这个相册中浏览, 放进来的图片数据用本地数据库进行保存 (主要是保存路径); 具体操作有展示图片, 添加图片, 删除图片;
屏幕快照 2018-11-16 下午 2.54.30.PNG-27.3kB
BaseView 和 BasePresenter 只是两个简单的接口
- public interface BaseView {
- }
- public interface BasePresenter {
- }
抽象接口
先看 View 层, View 是作为显示数据和交互的, App 只有三个功能, 那么 View 要做的就是:
展示图片
删除图片后会更新界面
添加本地图片后更新界面
再看 P 层, P 层是控制 Model 获取数据交给 View 显示的, App 只有三个功能, 那么 P 层要做的就是:
控制 Model 获取数据库的所有图片, 交给 View
删除图片, 通知 View 更新
保存添加的图片, 通知 View 更新
然后面对接口编程的思想, 我们把抽象出来接口, 这样子程序更清晰, 因为都是同一个功能, 所以抽象到一个类里面, 减少类的创建;
- public interface PicturesContract {
- interface View extends BaseView {
- // 显示图片, 刷新列表
- void showPic(List<Picture> pictureList);
- // 删除本地图片成功
- void deletePic(int position);
- // 添加本地图片
- void addPic(Picture picture);
- }
- interface Presenter extends BasePresenter {
- // 获取本地图片
- void getLocalPic();
- // 删除本地图片
- void deletePic(Picture picture);
- // 添加本地图片
- void addPic();
- }
- }
再看 Model 层, 新增一个 Picture 类来保存图片数据; 一般情况数据可能从内存, 本地或者网络获取, 这里只考虑本地; 对于 Model 来说, 就是数据库的增删; 所以提取出接口, 新建 PictureLocalDataSource 类来实现接口, 实现对数据库的操作, 这里和 Google 的 demo 里面一样, 使用的是 Google 的 Room 框架,
Android Room 使用: https://www.jianshu.com/p/7354d5048597
- /**
- * 对图片进行操作
- */
- public interface PictureDataSource {
- interface GetPicCallback {
- void onPicGet(Picture picture);
- }
- interface GetPicsCallback {
- void onPicGet(List<Picture> pictureList);
- }
- // 获取所有图片
- void getPics(GetPicsCallback getPicsCallback);
- // 获取一张图片
- void getPic(Long picId, GetPicCallback getPicCallback);
- // 删除一张图片
- void deletePic(Long picId);
- // 保存图片
- void savePic(Picture picture);
- }
具体实现
在 Activity 里面实现 PicturesContract.View 接口, 并且初始化控件, 做一下交互就 ok 了; 里面还需要初始化一个 PicturesContract.Presenter 对象, Presenter 类里面需要一个 PictureLocalDataSource 对象取操作数据和 PicturesContract.View 对象更新界面; 当用户相应操作的时候, Presenter 进行数据的操作, 成功后调用 View 更新界面. 关于对象的初始化, Google 官方的 demo 是新建一个 Activity,Activity 里面有一个 Fragement 作为 View 层, 在 Activity 里面进行一些初始化操作.
总结
具体就是这么来实现, M 层操作数据, V 层管理界面和交互, P 层负责将二者连接起来; 先将每层要负责的功能抽象出来, 在每层里面实现去. 界面和逻辑业务通过接口关联, 将业务实现细节隐藏, 如此一来, 当我们将交互之间的接口定义好之后, 内部的实现细节修改, 保证模块独立性.
一些疑问
其中也有一些疑问, M 层拿到图片数据 List 以后, 直接在 V 层给 Adapter 自己更新; Google 的 demo 也是这么做的, 就是说在 Activity 里面没有进行数据的保存, 那么如果要进行单个 item 的更新或者删除操作, 也需要在 Adapter 里面写方法; 结合 MVP 的思想, 数据在展示, 交互的时候改变了, 这个数据已经是保存在了 View 中了; 如果这些数据要保存起来, 就在 Persenter 里面调用 Model 来操作; 有疑惑或者不确定做的是否正确的时候就想想 MVP 思想.
- // 展示, 刷新图片
- @Override
- public void showPic(List<Picture> pictureList) {
- mPictureAdapter.replaceData(pictureList);
- }
项目地址: https://github.com/tyhjh/AndroidMvp
来源: http://www.jianshu.com/p/9050e3dbe513