热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

APP架子迁移指南(二)

接上一篇,这一篇开始用android来解释MVP概念、八股式的架子结构和命名规范。我在准备这篇文章的时候还看到不少在MVP基础上衍生的架子思路,底子是MVP没错,但命名有区别、复杂度变了、架子也用到了

接上一篇,这一篇开始用android来解释MVP概念、八股式的架子结构和命名规范。我在准备这篇文章的时候还看到不少在MVP基础上衍生的架子思路,底子是MVP没错,但命名有区别、复杂度变了、架子也用到了module拆分而不单纯用包进行拆分,所以接下来会基于googlesamples推荐的命名、架子结构来重构我的约炮APP,我会pull个新的branch来对应各个章节,接下来会从我认为合适的难度适中、实用的方向继续重构。

搭架子切忌过度!。搭架子就是为了隔离代码,该干嘛干嘛(说白了就是就是读数据的放一个文件夹,界面放一个文件夹)。现在流行的“domain”、“repository”、“Service”等命名,你若.net出家肯定会心一笑:“又TM来装逼了”--这些命名和早年的"module"、“Biz”、“helper”命名如出一辙(你可以去苏菲论坛看看大神几年前写的,至今也非常好用的那套.NET通用库)。

当你觉得看不明白的时候就该收手了。还是再强调一次这种观点,比如我为了准备文章看了这篇clean-architecture和这篇mosby。一脸的懵逼,并不是因为鸟语差,我可以毫不费劲的看完,而是因为我在看的时候脑海里一直深深的感觉“我有必要这样搞么?”,后面我突然明白,广点通2毛钱收入不是因为架子差,而是因为crash太多,哈哈哈。看不明白了还要继续装逼,就像刚开炉罩就寻思怎么承载千万级并发一样傻逼。你只要记住哪个文件夹放什么代码文件,干些啥这种层度,就足够受用了。

顺便预告一下,在后面讲IOS端,我会来讲讲MVC模式怎么结合搭架子的思路,正好也为出文章给点动力马拉松一次把一直想做的ios端做了(因为到现在用广点通收入才2毛钱不想弄,哈哈哈)。IOS现在炒MVVM火的很,关于MVVM模式我是很拒绝的,在早年做silverlight的时候用过,觉得太麻烦了(这也是我想提的观点,不要过度),数据绑定这件事,逻辑简单还好,要做很多其他工作,你光是写架子的基础代码就够折腾了。在后面讲PHP端(Laravel)的时候,我就聊聊文件夹该怎么放,文件名该怎么取显得很专业,以伟大又优雅的laravel框架来总结下全篇。

值得看的文章和项目

自从微博关注了很多大神和几个开发博客之后,各种技术文章炸屏有没有..尤其是像我这种好奇心胜的,关注的方向不少,看得很压抑啊。这里我先给几个我认为你应该学习的文章和项目,比我写的好、写的生动(打星标是指我认为的阅读友好度)。

  • Google原味mvp实践 ★★★★
  • Android:你是如何把Activity写的如此“万能”的 ★★★★
  • Android:“万能”Activity重构篇 ★★★★★
  • MVP+Dagger2+Retrofit实现更清晰的架构★★★
  • 从零开始的Android新项目6 - Repository层(下) Realm、缓存、异常处理★★★★(这个系列强烈推荐看完,大神还放了一个没混淆没加固已上线的apk让你逆向,感动)
  • Architecting Android…The clean way? ★★★
  • Architecting Android…The evolution ★★★
  • the-clean-architecture ★★★
  • Model-View-Presenter library for android ★★★

项目,要发现新的会编辑添加:

  • MVP殿堂级代码 ★★★★★
  • Crew(逆向看,注意dagger2会添加很多支持代码)★★

白话MVP模式

在学习架子的过程中,各种翻译差异和理解误差造成了诸多困扰,什么是“业务逻辑”?“领域层”?“数据映射层”?很烦有没有,尤其是早期网上的文章作者都是大神,觉得人民群众都是学霸,也不给点例子就用无比晦涩的描述带过去了。好在现在很多大神发现了这一点,开始用生动轻巧的语言来描述这些概念。前面推荐的文章相信你也吸收的差不多了,我就结合实际细节再白话一遍MVP模式(我没老司机带,理解偏差请纠错)。

你跟我一样吗

以前你是不是在一个叫data或者bean或者model的包里面放了很多数据实体?如“UserBean”,定义用户的名字、性别字段,添加get/set方法,持久化(Parcelable),用gson或orm的话还会加上@SerializedName、@Table之类的注入。


你定义数据的地方

接下来你会把网络访问哪个网址取得用户数据的代码写在一个叫Manager或者Api或者Network的包里面,json数据从网络读取并通过gson转换你会写在listview所在的fragment或者activity文件中(比如叫loadNewData)。


你定义网络访问的地方

你把网络访问数据转换为listview可读取数据的地方

如果你是有心之人,那么你还会写sqlite操作的逻辑并放在一个叫dao或者db的包,把数据写入到sqlite中去存起来。每次从数据库读或者写,会用asyncTask执行(可能你会新建一个叫task的包或者listview所在的fragment或者activity文件中,当时我图省事没弄)

如果你拿着票子想让功能更健壮,上传数据的代码写在service里面,那就会添加一个service包;需要添加notification,那么你会新建一个叫boardcase的包和notification的包,一个存广播、一个存notificaition;图片处理、时间字符串处理等功能写在一个叫utils的包里面;第三方轮子View控件写在一个叫widget的包里面。

发现啥问题没

写代码讲究个“逻辑分离”,简单讲读写数据的凑一堆;读写网络的凑一堆;界面交互(包括数据显示)凑一堆,这样的好处就是维护起来方便,易于扩展(项目小没这种体验?那在硬盘里面,代码放一个文件夹,ui设计素材放一个文件夹,文档放一个文件夹,要用的时候直接打开哪个文件夹心里了如指掌,这样理解了吧)。

那其他文章里总是提“业务逻辑”、“功能逻辑”,怎么区分呢。以登录功能来举例:

  1. 你用手机号或者微信登录,验证格式或者通过微信获取token和userinfo,都是为了实现登录功能,但是方法不同,完成这些操作你可以调用umeng或者第三方的原生SDK,为这些写代码,算业务逻辑。
  2. 把用户注册信息发送到服务器保存,并接收服务器反馈(比如保持用户登录状态的token),存进preference或者数据库,这些代码算业务逻辑。
  3. 怎么把数据就存入preference或者数据库,无非就是增删改查,那么这部分代码就算功能逻辑。

为实现具体业务功能写的代码,叫做“业务逻辑”。登录的时候获取人员位置、短信验证码都算。并且,你存入数据库之前需要修改服务器反馈的数据(比如从微信拿用户性别是m、f,你想存为0、1表示),这种代码也算入业务逻辑中去的。在各种架子中,“domain”、“service”、“repository”里面干的全是这些事。

为实现可复用的功能函数代码,叫做“功能逻辑”。不管业务是登录还是注销,想访问网络或者读取数据库,最后都会调用平台的方法吧,那么如何调用平台方法的代码,就是功能逻辑。如访问网络,不管是想post登录的网址或者post注销的网址,都会用到调用android网络访问的代码;如增删改查,不管你是preference或者sqlite,最后都会调用android方法执行;如数组转换、临时文件管理、图片压缩、检查字符串是否为空、md5加密、时间格式化等等,你可以写一个叫utils的包保存这些代码。boardcase、receiver、sevice、notifacation都应该以包为单位分离。


很多轮子已经帮你搞定了,比如读取图片的Glide或则网络访问的okhttp

按照这样的思路进行细分,那么很明显的,上一节中目前我app的框架虽然包的结果清晰,但是读起来是一团糟的,而且确实是“读”起来一团糟,比如index的fragment代码行数过高,我不得不简单的把代码“挪”到一个BaseIndexFragment中,简单的把数据读取和界面交互的代码分开便于阅读。MVP模式就很好的解决了我这样不专业的分离方案,提供了标准模板,什么代码该放哪就放哪。

Model层不再只是放数据实体了

按照MVP的说法,Model层是要把所有和数据有关的代码都放在这里的,也就是说定义数据实体、网络读取json并转换为数据数组、数据库读写数据这些代码全部都写在这里。Presenter层想获取数据,那就一定是已经处理好不需要再处理的数据了,怎么获取数据(从网络或者数据库)的、数据怎么转换的,通通都不用管。


数据处理全部移步Model层

在项目里面体现在什么地方呢,listview所在的fragment中,从网络获取json并转换为数据数组操作的代码从原来的loadNewData函数中移到了Model层的XXRemoteDataSource文件中去。从数据库获取数据的asyncTask代码移到了XXXLocalDatasource中去,判断显示本地数据还是网络数据的代码移到了XXXDataRepository中去。这样一来,fragment中的代码一下就清爽了很多,是不是感觉很好?我们继续看Presenter。

Presenter层就像电梯

数据读取前、读取后该干嘛?点击登录按钮后服务器返回登录状态该跳转首页还是提示密码错误?这些事都是Presenter干的:把Model层准备好的数据显示在界面上,有交互时提醒Model层数据需要更新。就像一台电梯,人进来,去按摩到3楼,去ktv到4楼,去开房到5楼。进来的是男是女你不需要关心,出去干嘛你也不需要关心。

在Presenter层里面会大量用到接口(interface)定义行为。以前是不用接口的,第一嫌麻烦,第二人家是团队这样方便测试,我只搞暴力测试没那么讲究。现在还是老老实实用吧,如果不习惯你可以先实现功能,再重构接口,或者把常用的增删改查先复制进去用,慢慢习惯。


要开始写接口了,有点心理准备

这时你可能会有一定的困惑,如果有涉及诸如IM通信、百度LBS定位这样功能逻辑的代码,该放哪里?这些代码可能需要依赖上下文(就是构造函数要context或者activity,你肯定见过),我认为应该放到utils包里面。传递参数、状态成功或失败该怎么处理的代码才放到Presenter中去。也就是说和界面有关的代码才放在Presenter中,其他按业务逻辑或功能逻辑能归类的尽量重构。

View层不是指的控件

这里的View是思想,不是具体指按钮控件或者列表。你可以脑补一个画面:View和Presenter在床(fragment或activity)上搞基,一会Viwe在上面,一会Presenter在上面。


View是让你在通知界面哪个该隐藏了,哪个该刷新了

从一个简单的新闻列表,到复杂点有轮播banner、多级下拉菜单,都可以在View层中表达控件的状态和交互动作,通知presenter这个控件被点击要执行啥操作了,或者prenseter通知这个控件应该被隐藏或显示了。View层在MVP结构中,反而是写代码量较轻的一块,只要Model和Presenter写好了,明天在github上看到一个更酷炫的轮子或者想添加一个动画效果,都是很清爽的事。

聊聊别的

我相信你已经看过我推荐的那几篇文章了,那么我这很白话的把mvp模式讲了一遍,用很多平时会用上的细节来解释,应该对概念的把握比较深刻了。那么在我把我的项目更新完成写下一篇之前,我们再聊聊别的。

RxJava和handler到底该用哪一个?

你们是不是也喜欢把自定义的handler写在fragment文件里面?或者asyncTask之类的,或者adapter。功能简单点的倒是问题不大,这样写又快又省事,阅读性也可以。但要是你遇上登录功能,首先通过umeng获取用户信息,成功了再从服务器获取七牛的上传token,然后传图片,图片上传成功把头像地址和用户信息post到数据库里面,成功了从服务器获取token存app数据库。像这样“圆环套圆环”的业务代码,画时序图都挺麻烦,用handler可以写,但是隔一段时间再阅读起来就很不开心了。


频繁的网络访问会让handler变得臃肿

RxJava的流编程思路就可以很好的解决这种问题,虽然代码量并不见得变少,但却是可以让阅读起来开心一点。至于网络模块你用async-http-client或者okhttp或者volley,或者最近很火的retrofit2,这就看自己了吧。我一直在用async-http-client,够老的轮子了吧,也没觉得有什么不妥的(可能我的网络访问规则太简单了)。另外你想当技术网红的话,RxJava+Retrofit2是必备神器,但要.net出家的人,还是呵呵吧,没必要炒到这种高度。

我的文章肯定有问题,求指正

我没老司机带,全靠github和逆向工程学习。肯定会有问题,还请发现了指正,非常感谢!qq群533838427


推荐阅读
  • 初探PLC 的ST 语言转换成C++ 的方法
    自动控制软件绕不开ST(StructureText)语言。它是IEC61131-3标准中唯一的一个高级语言。目前,大多数PLC产品支持ST ... [详细]
  • 一、Hadoop来历Hadoop的思想来源于Google在做搜索引擎的时候出现一个很大的问题就是这么多网页我如何才能以最快的速度来搜索到,由于这个问题Google发明 ... [详细]
  • flowable工作流 流程变量_信也科技工作流平台的技术实践
    1背景随着公司业务发展及内部业务流程诉求的增长,目前信息化系统不能够很好满足期望,主要体现如下:目前OA流程引擎无法满足企业特定业务流程需求,且移动端体 ... [详细]
  • Linux如何安装Mongodb的详细步骤和注意事项
    本文介绍了Linux如何安装Mongodb的详细步骤和注意事项,同时介绍了Mongodb的特点和优势。Mongodb是一个开源的数据库,适用于各种规模的企业和各类应用程序。它具有灵活的数据模式和高性能的数据读写操作,能够提高企业的敏捷性和可扩展性。文章还提供了Mongodb的下载安装包地址。 ... [详细]
  • 本文详细介绍了git常用命令及其操作方法,包括查看、添加、提交、删除、找回等操作,以及如何重置修改文件、抛弃工作区修改、将工作文件提交到本地暂存区、从版本库中删除文件等。同时还介绍了如何从暂存区恢复到工作文件、恢复最近一次提交过的状态,以及如何合并多个操作等。 ... [详细]
  • 2016 linux发行版排行_灵越7590 安装 linux (manjarognome)
    RT之前做了一次灵越7590黑苹果炒作业的文章,希望能够分享给更多不想折腾的人。kawauso:教你如何给灵越7590黑苹果抄作业​zhuanlan.z ... [详细]
  • 本文讨论了在使用Git进行版本控制时,如何提供类似CVS中自动增加版本号的功能。作者介绍了Git中的其他版本表示方式,如git describe命令,并提供了使用这些表示方式来确定文件更新情况的示例。此外,文章还介绍了启用$Id:$功能的方法,并讨论了一些开发者在使用Git时的需求和使用场景。 ... [详细]
  • 从壹开始前后端分离【 .NET Core2.0 +Vue2.0 】框架之六 || API项目整体搭建 6.1 仓储模式
    代码已上传Github+Gitee,文末有地址  书接上文:前几回文章中,我们花了三天的时间简单了解了下接口文档Swagger框架,已经完全解放了我们的以前的Word说明文档,并且可以在线进行调 ... [详细]
  • 初始化初始化本地空版本库,仓库,英文名repositorymkdirtest&&cdtestgitinit克隆项目到本地gitclone远程同 ... [详细]
  • 先记住几个专用名词,如下:Workspace:工作区IndexStage:暂存区Repository:仓库区(或本地仓库)Remote:远程仓库一、新建代码库#在当前目录新建一个G ... [详细]
  • 本文整理了Java中org.assertj.core.api.AbstractPathAssert.existsNoFollowLinks()方法的一些代码示例,展示了 ... [详细]
  • 论坛最近流量一直很大,pv却没增长多少,纠结啊,cdn的流量太贵了,跑不起啊最近mysql经常占cpu很高,今 ... [详细]
  • Git GitHub多人协作
    在学校做一个小项目需要多人协作,就用到了gitHub,百度了一下多数写得乱七八糟或者支离破碎,于是总结了一下自己的步骤如下,第一次使用GitHUb,哪里不对望大神指出一.前期准备: ... [详细]
  • 双十一在家学用 Git
    对于所有的开发者来说,掌握一门代码版本控制系统都是必须的,无论是自己做项目,团队合作,工作中的合作,都离不开版 ... [详细]
  • eclipse_在eclipse上使用github,向github中提交项目
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了在eclipse上使用github,向github中提交项目相关的知识,希望对你有一定的参考价值。 ... [详细]
author-avatar
滴滴答2502906673
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有