Android应⽤架构演变
引⾔
总结了多年的移动开发经验,特别是在Android端的积累,以前认为从移动端APP谈架构,其实有点举⼤旗,因为⼤部份项⽬都在做业务理,且往往不是很⼤,并没有多复杂的数据处理或⾼并发(只针对个⼈⽽⾔);并且长期认为架构这个词,⽤在Web端或者⼤型系统⾥⽐较好⼀点,好的架构好,意味系统更稳健、⾼效率, 更⼤体量。总之,有种⼤材⼩⽤的感觉,然⽽,随着Android应⽤开发规模的扩⼤,客户端业务逻辑也越来越复杂,已然不是简单的数据展⽰了,APP也需要进⾏架构设计,拆分视图和数据,解除模块之间的耦合,提⾼模块内部的聚合度。
APP 程序的结构
对于开发⼈员来讲,项⽬层⾯决定了如何搭建整个项⽬及划分模块,常⽤的Android程序结构:
UI层
数据展⽰与管理
⽤户交互
绘制
Adapter
业务逻辑层
持久化数据(内存中,相当于全局数据)
数据加式(数据层的数据有时候需要进⾏加⼯成UI层需要的数据)
数据变化的通知机制
数据层
数据访问(DB,⽂件,⽹络等)
缓存(图⽚,⽂件等)
配置⽂件(shared perference)
从程序结构看,架构在APP中⽆处不在,只是我们不太关注,最简单的Demo其实都有涉及架构(通常
是MVC)。从Android诞⽣⾄今,移动端的架构变更了很多次,从最初的MVC到MVP, 从冷门的Flutter(由RN引⼊到移动端)到Google的AAC/MVVM;好像架构的思想⼀直在变,但万变不离其中。下⾯将依次介绍MVC、MVP、MVVM这⼏种主流的架构设计,这⾥不会很深⼊的分析这些架构的代码上有何区别,只是分析它们的设计思路,在项⽬中⽅便的选择适⽤的架构。
MVC
⾮常经典的架构,不管哪个平台,都有这样的架构,好⽤⼜实惠。Android采⽤XML⽂件实现页⾯布局,通过Java在Activity中开发业务逻辑,这种开发模式实际上已经采⽤了MVC的思想,分离视图和控制器。MVC模式(Model–view–controller)是软件⼯程中的⼀种软件架构模式,把软件系统分为三个基本部分:模型(Model)、视图(View)和控制器(Controller)。
:
MVC模式最早由Trygve Reenskaug在1978年提出,是施乐帕罗奥多研究中⼼(XeroxPARC)在20世纪80年代为程序语⾔Smalltalk发明的⼀种软件架构。MVC模式的⽬的是实现⼀种动态的程序设计,使后续对程序的修改和扩展简化,并且使程序某⼀部分的重复利⽤成为可能。除此之外,此模式通过对复杂度的简化,使程序结构更加直观。软件系统通过对⾃⾝基本部分分离的同时也赋予了各个基本部分应有的功能。专业⼈员可以通过⾃⾝的专长分组:
控制器(Controller)- 负责转发请求,对请求进⾏处理。
视图(View) – 界⾯设计⼈员进⾏图形界⾯设计。
模型(Model) – 程序员编写程序应有的功能(实现算法等等)、数据库专家进⾏数据管理和数据库设计(可以实现具体的功能)。
在Android编程中,View对应xml布局⽂件,Model对应实体模型(⽹络、数据库、I/O),Controller对应Activity业务逻辑,数据处理和UI处理。如下图所⽰:
//Model
public interface WeatherModel {
void getWeather(String cityNumber, OnWeatherListener listener);
}
................
public class WeatherModelImpl implements WeatherModel {
@Override
public void getWeather(String cityNumber, final OnWeatherListener listener) {
/*数据层操作*/
Weather.class, new Response.Listener<weather>() {
@Override
public void onResponse(Weather weather) {
if (weather != null) {
} else {
}
}
}, new Response.ErrorListener() {
@Override
android编程入门指南 pdfpublic void onErrorResponse(VolleyError error) {
}
});
}
}
//Controllor(View)层
public class MainActivity extends ActionBarActivity implements OnWeatherListener, View.OnClickListener {
private WeatherModel weatherModel;
private EditText cityNOInput;
private TextView city;
...
@Override
protected void onCreate(Bundle savedInstanceState) {
setContentView(R.layout.activity_main);
weatherModel = new WeatherModelImpl();
initView();
}
//初始化View
private void initView() {
cityNOInput = findView(_city_no);
city = findView(R.id.tv_city);
...
findView(R.id.btn_go).setOnClickListener(this);
}
/
/显⽰结果
public void displayResult(Weather weather) {
WeatherInfo weatherInfo = Weatherinfo();
WeatherInfo weatherInfo = Weatherinfo();
city.City());
...
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.btn_go:
break;
}
}
@Override
public void onSuccess(Weather weather) {
displayResult(weather);
}
@Override
public void onError() {
Toast.makeText(this, 获取天⽓信息失败, Toast.LENGTH_SHORT).show();
}
private T findView(int id) {
return (T) findViewById(id);
}
}
例⼦分析:
Activity⾥⾯的控件必须关⼼业务和数据,才能知道⾃⼰怎么展⽰。
所有的逻辑都在activity⾥⾯。
因此,在实际开发过程中,纯粹作为View的各个XML⽂件功能较弱,Activity基本上都是View和Controller的合体,既要负责视图的显⽰⼜要加⼊控制逻辑,承担的功能很多,导致代码量很⼤。所有更贴切的⽬前常规的开发说应该是View-Model模式,⼤部分都是通过Activity的协调。
MVP
MVP是从MVC过渡⽽来,MVP架构由三部分组成:View负责显⽰,Presenter负责逻辑处理,Model提供数据。Android开发从MVC过渡到MVP,最主要的变化就是将Activity中负责业务逻辑的代码移到Presenter中,Activity只充当MVP中的View,负责界⾯初始化以及建⽴界⾯控件与Presenter的关联。
例如,MVC中,在业务逻辑稍微复杂⼀点的页⾯,Activity的代码超过⼀千是很容易的,但Activity并不是⼀个标准的MVC模式中的Controller,它的⾸要职责是加载应⽤的布局和初始化⽤户界⾯,并接受并处理来⾃⽤户的操作请求,进⽽作出响应。随着界⾯及其逻辑的复杂度不断提升,Activity类的职责不断增加,以致变得庞⼤臃肿,那⾃然会想到进⾏拆分。这样拆分之后,Presenter承担了⼤量的逻辑操作,避免了Activity的臃肿。整个架构如下图所⽰:
//Model层
/**
* 定义业务接⼝
*/
public interface IUserBiz {
public void login(String username, String password, OnLoginListener loginListener);
}
/**
* 结果回调接⼝
*/
public interface OnLoginListener {
void loginSuccess(User user);
void loginFailed();
}
/**
* 具体Model的实现
*/
public class UserBiz implements IUserBiz {
@Override
public void login(final String username, final String password, final OnLoginListener loginListener) {
//模拟⼦线程耗时操作
new Thread() {
@Override
public void run() {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
//模拟登录成功
if ("zhy".equals(username) && "123".equals(password)) {
User user = new User();
user.setUsername(username);
user.setPassword(password);
loginListener.loginSuccess(user);
} else {
loginListener.loginFailed();
}
}
}
}.start();
}
}
//View
public interface IUserLoginView {
String getUserName();
String getPassword();
void clearUserName();
void clearPassword();
void showLoading();
void hideLoading();
void toMainActivity(User user);
void showFailedError();
}
//然后Activity实现这个这个接⼝:
public class UserLoginActivity extends ActionBarActivity implements IUserLoginView { private EditText mEtUsername, mEtPassword;
private Button mBtnLogin, mBtnClear;
private ProgressBar mPbLoading;
private UserLoginPresenter mUserLoginPresenter = new UserLoginPresenter(this);
@Override
protected void onCreate(Bundle savedInstanceState) {
setContentView(R.layout.activity_user_login);
initViews();
}
private void initViews() {
mEtUsername = (EditText) findViewById(R.id.id_et_username);
mEtPassword = (EditText) findViewById(R.id.id_et_password);
mBtnClear = (Button) findViewById(R.id.id_btn_clear);
mBtnLogin = (Button) findViewById(R.id.id_btn_login);
mPbLoading = (ProgressBar) findViewById(R.id.id_pb_loading);
mBtnLogin.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mUserLoginPresenter.login();
}
});
mBtnClear.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mUserLoginPresenter.clear();
}
});
}
@Override
public String getUserName() {
Text().toString();
}
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论