前言

Web的架构经过多年的发展已经非常成熟了,我们常用的SSM,SSH等等,架构都非常标准。个人认为,Web服务逻辑比较清晰,目的明确,流程也相对固定,从服务器收到请求开始,经过一系列的的拦截器,过滤器->被转发到控制器手中->控制器再调用服务->服务再调用DAO获取想要的数据->最后把数据返回给web层。哪怕中间增加一些东西,如缓存什么的。他的模型依然是以用户请求的线程为生命周期,经过一个个切面(层)的结构,感觉类似于流水线的结构吧。 
 
而Android App则有所不同,他没有像用户请求这样一个统一的出发点,最接近的可能是来自于UI的事件,然而远不仅仅于此。根据app不同的需求,其结构也会千差万别,所以很难有较为统一的架构。 
但是客户端类app确实是较为常见的App类型,其结构还是有迹可循的。

常见的架构

一.MVC 
mvc现在是用的人最多,同时也是Android官方的设计模式,可以说Android App原本就是MVC的,View对应布局文件xml,Controller对应Activity,Model对应数据模型。 
 
这类App一般会定义一个BaseActivity,BaseActivity内部实现了网络的异步请求,本地数据的存储加,数据库访问载等复用性较强的逻辑。逻辑控制则在对应的Activity中实现。 
MVC的缺点:Activity过于臃肿,往往一个Activity几百上千行代码。View层的XML控制力其实非常弱,众多的View处理还是要放在Activity进行,这样的话,Activity就既包含了View又包含了Controller,耦合高,不利于测试扩展,可读性也变差。


二.MVVM 
用过VS开发过.net的人肯定知道MVVM的强大之处,仅需要点点鼠标,数据库里的信息和View的控件显示就被简单的绑定了。 

而Android的数据绑定个人认为还是不够成熟的,用法长这样android:text=”@{user.username}”/> 
在xml里面配置数据模型。一是控制力不够,二是部分逻辑需要放到数据Model里处理。


三.MVP 
最近在Android上应用比较火的模式。相较于MVC,MVP将Activity中的业务逻辑抽取出来,将Activity,Fragment等作为View层,专职与界面交互。而Presenter则负责数据Model的填充和View层的显示。View不直接与Model交互,解耦了Actiity。 
 
这样可以做到逻辑和界面交互的完全分离,方便测试,界面升级等。代码的可读性也大大增加。

个人的设计

对于我自己,在我自己架构项目的时候确实遇到了一些困难,也有选择障碍,经过一番思考。我有了自己的见解,总体还是偏向于MVP,但又有些不同。可能是MVP+MVVM(伪)吧。

首先是包结构 
 
1.View层 
view层按照Android组件的分类,可以使用接口通信,也可以使用类似EventBus的事件框架进行通信 
Action包就是事件实体,这里使用的是我自己实现的事件框架。 


2.Model层 
model层包含数据模型,实体类,以及dao,http等数据获取得代码。回掉的话可以使用接口,也可以使用事件框架。另外缓存也放在这里。 


3.Presenter 
包含Base(自己实现的Presenter框架,其实就是将Activity抽取了一层),Service包是Android组件Service 
Impl是业务的实现,下面一堆I开头的是业务接口。 
 
这里讲一下Base,Base相当于控制器,拿登陆来举例,一个登陆操作可能涉及多个界面,多个业务逻辑单元。比如登陆,首先是请求网络的逻辑,除此之外,登陆成功后,需要对会话,用户基础信息等进行持久化;还有控制器需要控制各个界面的刷新。这些都是在控制器Base中完成的,他是一组逻辑的控制单元,负责一个典型的业务,比如说登陆。


下面的重点是业务接口,例如登陆ILogin,如果自己实现,你需要写一大堆的东西,网络请求,异步处理,Handler,异常处理,JSON解析,显示,洋洋洒洒至少上百行了。如果你的项目需要快速上线怎么办?同时你又想保持项目的逻辑结构,以后做更细致的改进,这时候就体现了接口的重要性。这里安利我一个比较快速的实现链接也是我实现的一个小框架。 
用起来画风是这样的。

public class LoginPresenter extends Presenter implements ActivityOnCreatedListener,ICallBack<User,Throwable>{private ILogin ILogin;@Overrideprotected void onContextChanged(ContextChangeEvent event) {}@Overridepublic void OnPresentInited(Context context) {ILogin = HttpProxyFactory.With(ILogin.class).setCallBack(this).setViewContent(getActivityRaw()).establish();getActivityInter().setOnCreateListener(this);}@Overridepublic void ActivityOnCreated(Bundle savedInstanceState, final Activity activity) {getActivityInter().getView(R.id.btn_login).setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {LoginActivity ac = (LoginActivity) activity;ac.progressDialog.show();getActivityInter().getView(R.id.btn_login).setClickable(false);EditText name = getActivityInter().getView(R.id.login_name);EditText pass = getActivityInter().getView(R.id.login_pass);ILogin.login(name.getText().toString(),pass.getText().toString());}});}@Overridepublic void onSuccess(User user) {Log.e("gy",user.toString());getActivityRaw().finish();navTo(HomeActivity.class);}@Overridepublic void onFailed(Throwable throwable) {ILoginCallBack callBack = (ILoginCallBack) getContext();callBack.onLogFailed(throwable.getMessage());}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45

你可以发现ILogin = HttpProxyFactory.With(ILogin.class).setCallBack(this).setViewContent(getActivityRaw()).establish(); 
这么简单,你的ILogin业务接口就被框架实现了,简单的说就是用了动态代理,框架根据你在接口上绑定的注解信息,帮你动态代理处一个业务实现对象。帮你包办了网络请求,异步处理,异步回掉,异常处理,JSON解析,显示等一大堆操作。 
如何绑定你的需求?

ILogin接口张这样的

public interface ILogin {@HttpSrcMethod(url = "/store/login",session = Global.SKEY_UNLOGIN,filters = ResultFilter.class)public User login(@Param("tel")String name,@Param("password")String passwd);
}
  • 1
  • 2
  • 3
  • 4

返回值模型Model User比较简单,我们换一个比较典型的

@JsonOrm
public class ResultArea implements IHandler{@JsonString("name")private String name;@JsonString("id")private String id;@BindListView(CityPickerActivity.ListViewId)@JsonSet(name = "areas",clazz = Area.class)private List<Area> child;public String getName() {return name;}public void setName(String name) {this.name = name;}public String getId() {return id;}public void setId(String id) {this.id = id;}public List<Area> getChild() {return child;}public void setChild(List<Area> child) {this.child = child;}@Overridepublic void handler() throws Exception {if (child == null)child = new ArrayList<>();child.add(0,new Area(name,id));}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42

注解几乎映射了你所有的业务接口协议,包括请求参数,URL,头,返回值的json映射,对应View层的视图显示等等。

使用这种临时解决方案之后,后期如有需求,自己再选用其它框架,或者自己实现业务接口即可,根本不需要动其他模块,从而保证了可扩展性。

Android App架构设计相关推荐

  1. Android APP架构设计——MVP的使用示例

    0. 前言 为了更好地进行移动端架构设计,我们最常用的就是MVC.MVP和MVVM,作为三个最耳熟能详的三大架构,应用可谓非常广泛.对于这三种架构设计以及优缺点已经在Android APP架构设计-- ...

  2. Android App 架构设计相关资料汇总

    1. 前言 只要有1,2年工作经验的程序员,多多少少都会接触到架构东西.可能平时工作中不一定会有机会从0到1完完全全自己去设计一套架构出来,但是如果想成为高级工程师,技术专家,架构师--尽早接触架构方 ...

  3. Android App的设计架构:MVC,MVP,MVVM与架构经验谈

    本文转载自https://www.tianmaying.com/tutorial/AndroidMVC,原文作者周鸿博. 和MVC框架模式一样,Model模型处理数据代码不变在Android的App开 ...

  4. App架构设计经验谈:展示层的设计

    2019独角兽企业重金招聘Python工程师标准>>> App架构设计经验谈:展示层的设计 三层架构中,数据层和业务层都已经做过了简单的分享,最后,就剩下展示层了.本篇就给各位分享下 ...

  5. android客户端框架,最新的一版,通用Android 客户端架构设计,只有你还没看过

    客户端架构设计 客户端设计 目的是整体设计客户端App,架构上打好铺垫. Android客户端架构设计 主要从以下几个方面进行设计:MVP设计风格.整体架构.日志系统.网络系统.本地存储.Test模块 ...

  6. Hybrid APP架构设计思路

    转自: https://segmentfault.com/a/1190000004263182 关于Hybrid模式开发app的好处,网络上已有很多文章阐述了,这里不展开. 本文将从以下几个方面阐述H ...

  7. Android APP架构心得

    前言 从JavaEE转到Android开发也2年多了,开发的项目也有4,5个了(公司项目),其中有3个项目前期都是自己独立开发,从一开始的毫无架构到现在对如何架构也有一点心得,所以在此分享出来,大家一 ...

  8. 一种Android客户端架构设计分享

    转载请注明出处:http://blog.csdn.net/ahence/article/details/56678126 技术发展日新月异,业界各种Android客户端架构设计,五花八门,但我们不能简 ...

  9. App架构设计经验之谈

    App架构设计经验之谈 1.接口的设计 1.1安全机制的设计 由于App的接口大部分采用RESTful架构,而RESTFul最重要的一个设计原则-客户端与服务器的交互的无状态性,所以,当涉及到用户状态 ...

最新文章

  1. 必须对手机内置业务制定规范防止后门
  2. lograotate 配置常用配置
  3. (三)opencv_py之阈值处理
  4. mysql 开发基础系列22 SQL Model(带迁移事项)
  5. CV+游戏,美国游戏开发公司 Rockstar Games 寻找优秀动画程序员
  6. 螺旋进刀非法平面选择_进刀方法、刀片类型、术语...螺纹加工重点知识你都知道吗?...
  7. [GoogleAppEngine]GAE平台需设置默认threadsafe-编译问题
  8. 计算机系统-CPU优化/特权级
  9. js空格占位符_灵活使用 console 让 js 调试更简单
  10. python选股并导入通达信自选股
  11. JDKAndroid下载安装
  12. SmartUpload
  13. 停止dockerd进程
  14. 商标注册服务的详细讲解
  15. 鸿蒙版瑞幸咖啡开发日记(六)详情页与首页联动
  16. iReport —— A4打印,只占纸张的一半,如何解决
  17. 关于Unity打不开弹出“由于找不到MSVCP140.dll,无法继续执行代码,重新安装程序可能会解决此问题”解决方案
  18. 正数的原码,反码,补码
  19. 电动车电池管理系统c语言实训,电动车控制器C语言源代码复习课程.doc
  20. centos修改系统可用内存_centos7开启交换内存

热门文章

  1. Oracle的表字段带有双引号,Mybatis报 An identifier or literal is invalid
  2. Oxyplot实时绘图学习笔记(下)
  3. linux. qt信号崩溃,【创龙AM4379 Cortex-A9试用体验】之I/O中断异步通知驱动程序+QT捕获Linux系统信号+测试信号通知...
  4. React云音悦WebApp
  5. Centos7 配置163邮箱
  6. 我用自己的亲身经历告诉你为什么不建议你合租!
  7. 怎么用计算机计算年月份,win7计算器怎么计算某年某月某日到某年某 – 手机爱问...
  8. 3ds模拟JAVA游戏_3ds模拟器Citra3ds下载
  9. Mockplus Cloud Crack,项目管理顺畅
  10. 清歌输入法 for Mac(最好用的五笔输入法