3分钟理解android-architecture 之 todo-mvp-clean

相信很多人star或者fork过googlesample上的这份代码?也一定有很多人看到过这幅图?

Paste_Image.png

然而,不知道是个人愚笨还是别的其他原因,我总觉得这幅图表达的不是那么详细,Domin Layour到底是个什么鬼,这里没有说得太明白?虽然他是那个老头(uncle bob)的思想,但似乎对我来说有点抽象,所以,我决定让他show me the code

把抽象具体化

不过,大家先不要着急,我这里不是要坑大家和我一起读代码的,因此我也准备了一幅图让大家对架构有一个整体认识,自认为用来解释这上面那副抽象的图会比较有用。

Paste_Image.png

请原谅我非常糟糕的画图能力,看到这里,时间应该已经过了1分钟了,那么接下来还有2分钟的时间来理解这个架构。

具体是需要步骤的

我觉得有必要用一个简单的用例将整个流程窜一下:

  • step1.用户点击了一个刷新列表的请求,此时我们就简单的假设是view上的某个按钮触发出来的,也别想的太复杂。就比如说这段代码:(对不起,有时候show me the code is the best way...)
Paste_Image.png
  • step2. presenter当然是最先感知到这个事件的,如是,他让UseCaseHandler去执行UseCase,大家知道,因为耗时操作通常不应该丢在UI线程中去处理,因此,执行UseCase这项艰巨的任务应该是交给一个比较有地下工作能力的人去处理的(实际上更加准确的说是有能力制造一个地下工作环境的人),那么这个人就是UseCaseScheduler,那么当执行完成之后,他需要通过回调通知到presenter,presenter然后在通知VIEW更新视图,对吧?确实如此,来看看代码呗:
Paste_Image.png

确实,UseCaseHandler粗线了!回调callback也出现了,UseCaseScheduler呢?跑哪里去了?,还有UseCase呢,跑哪里去了?别急,看看execute就知道了:

Paste_Image.png

哦,原来,那个Task本身就是一个UseCase,handler实际执行UseCase的时候是交给UseCaseScheduler的也没有错,那么回调呢?

Paste_Image.png

Paste_Image.png

哈哈,回调也出来了,然来这一起都是useCase自导自演的一场戏,那么等等,好像有点不对啊,为什么callback需要UiCallBackWrapper这么传给UseCase呢?

Paste_Image.png

好,我们回过头想一下,我们的UseCase真个执行时交给UseCaseScheduler这个具备超强幕后工作能力的家伙干的对吧,因此,UseCase的所有操作将会在幕后发生,因此:

Paste_Image.png

那么请问,如果第一段代码在非UI线程中执行,那么,第二段代码会在哪里执行?答案肯定是非UI线程,众所周知,非UI线程操作UI势必会造成app崩溃,那么,请看这段代码?

Paste_Image.png

我想,此刻的你应该有点晕了?那么别急,看玩这幅图,想必你又好了。

Paste_Image.png

事实上,这个UiWrapper最后将最后的callback的执行权交给了UseCase,而此时,callback的执行环境已经变化了,没错,发生在了主线程。这个模式我不知道叫什么,但是我之前也是经常用到,常常自称为“多级代理模式”。呵呵,你也许会说,google这帮人怎么这么能折腾,干嘛不直接这样?

Paste_Image.png

,我可以负责任的说,确实可以跑,也不需要那个UiWrapperCallback那么绕,但是,但是:

Paste_Image.png

UseCase他依赖到了Android层面的东西,这有点违背了clean的思想不是吗?

其实,到这里已经算是读懂了google的这样一个关于架构的sample了。但是你不想在看看step3嘛?

  • step3. Repository本身也是DataSource,为何还需要在详细的区分为LocalDataSource和一个RemoteDataSource?事实上,很多时候网络并不是我们的朋友,做一个本地缓存对我们的app的用户体验的提升是非常有帮助的,如果这一部分需要详细讲,我觉得有必要在开一篇文章,专门的去谈,《如何使我们的app离线化》,这里,我们就简单的看看做两个数据源的好处吧:
Paste_Image.png
Paste_Image.png

从上面可以看出,这里实现了这么一种功能,如果本地缓存有数据,且不是用户强刷的情况下,直接取本地缓存数据,那么如果本地缓存失效了,取网络数据,切更新本地缓存。其好处是,速度快,节省用户流量。

好了,到此为止,关于googlesample 之 clean的这个架构已经分析完成了,相信你之前遇到的一些问题级困惑在这里也找到的答案。

但是因为这个架构对离线化这块做的比较简单,因此,打算有时间在写一篇,关于如何做好app离线化的文章,也是是在此基础上丰富这个优秀的框架吧。

推荐阅读更多精彩内容