这段时间在了解MVP的框架 网上也有一些示例写的也很好 正巧看到官方也推出了基于MVP的示例Demo 所以想试着了解下 顺便写下此笔记
其实网上也已经有对MVP进行了解析的文章Android官方MVP架构示例项目解析说的也很好 但是关于M方面不是很理解 所以自己试着解析下
先上一张图MVP的结构图
什么是MVP ? 为什么使用MVP 他有什么优缺点 ? 这里我就不赘述了 这篇文章已经都说到了想更多的是解释示例MVP的代码
官方给出的示例MVP流程图
现在看着可能似懂非懂 这样我们先 Read the fucking source code 再回来看图!
项目在GitHub上面有 我是地址
先看下目录结构
可以看出分包是根据模块进行的分包
基类
首先是View 和 Presenter 的基类 定义start setPresenter 方法 什么作用下面说
接下来是Model 这个可能跟View 的基类什么的还不是太一样 因为接下来的所有的Presenter都用同时用到它
这里面谷歌还弄了一个叫做契约类的东东 是一个接口 定义内部接口继承View 和Persenter基类
定义方法 到时候V 和 P 直接实现这里面的接口就可以了 并且有什么方法都会在这里 确实是看方法的时候简洁明了
那么下面我们就开始
首先是进入主TasksActivity 我们只看主要代码其他初始化控件什么的就不看了
可以看到 onCreate方法里面 显示直接创建TasksFragment对象 并且添加到了Activity
并且TasksFragment 是直接实现的契约类的TasksContract.View基类
接下来创建TasksPresenter对象 并且传入了TasksFragment对象和 Model对象 这里的Model先这么记得 因为它里面并不是那么简单
小总结:
1实现类并不是直接实现的基类 而是创建了一个契约类来实现 来更好的管理实现类中的方法
2 这里面的Activity并不是我们MVP中对应的V 而是Fragment Activity只是负责管理创建 V P M 的对象使他们相互关联 从而达到相互调用
既然TasksFragment 和 TasksPresenter 对象都已经创建了 我们就进去看看里面是怎么实现的
TasksPresenter
实现TasksContract.Presenter契约类接口 在构造里面接受 Model 和 View 的对象,并且调用了View 的setPresenter方法 并且把自己的引用传了进去 这就是上面基类定义的方法,这样Presenter就有了View的引用 View也有了Presenter的引用。
还可以看到下面 实现了start方法 并且调用了 loadTasks方法 这个方法其实是用来加载数据使用的 一会在说是谁调用他的 和他的调用时机。
TasksFragment
我们在回头看TasksFragment的实现
创建对象 可以看到onResume方法里面调用了Presenter的start方法 就是当界面可见并且运行起来的时候 调用start方法 在调用刚才上面说的loadTasks加载数据
还可以看到我们实现的setPresenter 接受了Persneter引用
小总结:
1 Presenter 拿到View引用 调用setPresenter传入自己的引用, View在拿到Presenter引用 在生命周期方法onResume中调用start方法加载数据
接下来我们在看loadTasks方法的实现 因为屏幕小截图不够一张 原谅我多截几张(手动调皮脸)
调用了TasksRepository的getTasks 方法 那么现在我们就要说一下这个TasksRepository的引用是怎么回事了
还记得刚开始的时候 我们通过构造传入进来的TasksRepository对象是怎么生成的么
其实是调用了上面这个的类的方法 并在再返回的时候 创建了 TasksRepository 的对象 并传入了 FakeTasksRemoteDataSource 和 TasksLocalDataSource 的引用 才返回的 那么我们进入去看看 这个里面引用到底是什么 搞清了他 一会我们在看getTasks 方法的时候才能看懂
再看下Data的目录结构
可以看到 这两个引用 和我们的Model对象都是实现了 我们刚开始定义的Model基类 现在可以说明的一点就是这几个类都是提供数据的 并且这些类都实现了 getTask方法
FakeTasksRemoteDataSource
类描述 :Implementation of a remote data source with static access to the data for easy testing. 大概的意思就是 用来实现静态的远程数据访问测试
哦 跟咱们猜的差不多 提供数据的 但是他是提供远程数据源的 也就是模拟我们在网上获取数据的 只是获取数据的一种方式
getTask方法 从一个Map中获取数据
TasksLocalDataSource
类描述:Concrete implementation of a data source as a db.
哦 又猜的一样 是一个基于数据库的数据源 又是一种获取数据的方法
这里面的getTask也是一样获取数据 代码太多 就不贴了
那么我们现在搞明白了这两个引用分别都是以不同方式来模拟获取数据的 并且还传入到了TasksRepository中 那这时候我们就来看看TasksRepository的getTask是怎么实现的
接受LoadTasksCallback 对象 这个其实是刚开始声明在Model基类中的 内部接口
声明了两个方法 其实就相当于我们的 请求数据成功和失败一样
然后判断缓存是否存在 和缓存是否可用 如果都可用 那么回掉接口方法 并且把缓存的数据全部取出来返回
然后判断缓存是否可用 不可用 调用getTasksFromRemoteDataSource 方法
可以看到里面调用了 上面我们传入给TasksRepository中的 远程数据获取的引用 并且调用了getTask方法 获取数据 如果获取成功 添加缓存 并且添加本地 在回掉成功 传入数据
如果可用 会调用获取 本地数据源引用的getTask方法 加载数据 成功的话在添加到缓存 然后成功回掉
这时候 我们看他会调成功后 循环 根据任务类型进行添加数据 最后调用 processTasks 方法 传入数据 如果数据没问题 就调用TasksFragment的showTasks方法 展示数据
到此为止 这个流程就是走完了
这时候 我们在来看看 上面官方给出的图 右边 首先是由Activity管理 View也就是Fragment 和Presenter 的创建和关联 然后再让Model和 Perstnter相互引用
左边 可以看到Model本身有缓存机制 并且分别创建了 本地数据源 和远程数据源
最后其实官方的示例中还涉及到了测设部分 因为不太了解 就不做重点了解了
其实官方给我们 只是一种示例 我们不一定非要用Framgent当View 也不一定非要把Model写成这种模式 但是这种方法感觉也还是值得借鉴的 我们也可以根据我们项目的自身需求 来编写不同写法 希望大家不要被具体的代码所困住
本篇到此就结束了 总的来说代码还是很简单的 不过还是要多多使用才能更加深刻的理解MVP 好了 希望大家不喜勿喷 有错误的地方还请多指教 再见 !