Android APP架构总结

为了理解与分析APP源码,需要知道APP是怎么开发出来的。了解当前主流的APP开发架构,便于在分析dex的时候就能够有的放矢,抓住重点。

一个APP的核心是数据,根据其数据处理的模式这里暂时总结出两类:

  • 数据展示类:我们平时使用的绝大多数应用都可归为此类,如即时通讯类APP,频繁与服务端进行数据交互,并实时显示在页面中;社交、购物和资讯类APP,将服务端发来的数据列表显示在页面中,将用户在设备上的操作产生的数据回传给服务端。
  • 系统工具类:主要调用系统接口,将少量设备信息、APP状态信息等传回服务端。

从用户的角度来看,应用启动的过程是:点击APP图标->设备显示APP页面数据和功能->用户与页面交互。APP开发时,承载这一过程的主要组件就是Activity。开发者通过View设计页面布局,Activity作为载体显示界面,并实现交互逻辑。比较基础的应用就会将数据管理、文件操作、网络数据传输等功能直接由Activity或Framework调用。

但是,当页面功能较为复杂时,就会维护困难。而Activity或Framework中复杂的数据运算或网络通信会导致用户交互时页面反应变慢,造成“卡顿”的既视感,因此,考虑将数据处理逻辑分离出去。


根据程序设计的原则(面向对象原则、单一职责原则、开闭原则、里氏替换原则、依赖倒转原则、接口隔离原则),目前主流的架构方案有MVC、MVP、MVVM等。

1. MVC

MVC即model,view,controller。

  • Model:负责处理数据的加载或存储
  • View:负责数据展示,与用户进行交互
  • Controller:负责处理业务逻辑

其流程为:View接收用户输入,然后将请求传递给Controller,Controller再调用某个Model来处理用户的请求,再由Controller将处理后的结果交给某个View输出给用户。

以简单的用户登录为例:

项目目录:

首先,定义一个Person的bean类:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public class Person {
private String username;
private String password;

public String getUsername() {
return username;
}

public void setUsername(String username) {
this.username = username;
}

public String getPassword() {
return password;
}

public void setPassword(String password) {
this.password = password;
}
}

定义一个回调接口OnPersonListener:

1
2
3
4
public interface OnPersonListener {
void onSuccess(Person person);
void onFailure();
}

再定义一个接口PersonModel,并实现PersonModelImpl:

1
2
3
4
5
6
7
8
9
10
11
public class PersonModelImpl implements PersonModel {
//在此处写相应逻辑
@Override
public void login(Person person, OnPersonListener onPersonListener) {
if(person.getUsername().equals("123")&&person.getPassword().equals("123")){
onPersonListener.onSuccess(person);
}else {
onPersonListener.onFailure();
}
}
}

Activity中实现业务逻辑:

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
public class MainActivity extends AppCompatActivity implements OnPersonListener,View.OnClickListener {

private EditText et_username;
private EditText et_password;
private Button btn_login;
private String username;
private String password;
private PersonModelImpl personModel;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
init();
personModel = new PersonModelImpl();
}

//控件初始化
private void init() {
et_username = (EditText)findViewById(R.id.et_username);
et_password = (EditText)findViewById(R.id.et_password);
btn_login = (Button)findViewById(R.id.btn_login);
btn_login.setOnClickListener(this);
}

@Override
public void onClick(View v) {
username = et_username.getText().toString();
password = et_password.getText().toString();
Person person = new Person();
person.setUsername(username);
person.setPassword(password);
personModel.login(person,this);
}

@Override
public void onSuccess(Person person) {
Toast.makeText(this, "登录成功", Toast.LENGTH_SHORT).show();
}

@Override
public void onFailure() {
Toast.makeText(this, "登录失败", Toast.LENGTH_SHORT).show();
}
}

可以看到主要的业务逻辑是在Activity中实现的,把上述示例中Onclick()实现独立出去为一个新建的Controller类,就是一个更明显的典型MVC模式。

其实,初学者就是以MVC的思路在开发,但是面对较为复杂的应用,Activity作为Controller的负担就会过重,APP功能扩展,程序复用上就会面临较多问题。

2. MVP

MVP:Model-View-Presenter,基本思想与MVC相通,即将数据显示、数据处理和业务逻辑分开。具体实现则不相同,这里Presenter相当于中间桥梁的作用,View显示数据直接访问Presenter,由Presenter请求Model。Model处理完数据后返回给Presenter, 再由Presenter交给View显示。整个过程中的交互都由Presenter进行,Presenter同时持有View和Model的对象的引用,才能在它们之间进行通信。

Activity和Fragment在这个MVP模式中被抽象为View,所有的业务逻辑,与数据处理相关的部分都交给Presenter去与Model交互。

MVC架构中的例子,用MVP架构表达如下:

View接口:

​ public interface IPersonView{

​ void showPerson(String result);

​ }

Presenter层:

public class PersonPresenter{

​ private IPersonView personView;

​ private IPersonModel personModel;

​ public PersonPresenter(IPersonView personView){

​ this.personView = personView;

​ personModel = new PersonModel();

​ }

// 业务逻辑

​ public void login(Person person){

​ personModel.login(person, new onPersonListener(){

​ @Override

​ public void onSuccess(Person person) {

​ personView.showPerson(“登录成功”);

​ }

​ @Override
​ public void onFailure() {
​ personView.showPerson(“登录失败”);
​ }

​ });

​ }

}

Activity:

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
public class MainActivity extends AppCompatActivity implements  IPersonView,View.OnClickListener {
private EditText et_username;
private EditText et_password;
private Button btn_login;
private String username;
private String password;
private PersonPresenter personPresenter;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
init();
personPresenter = new PersonPresenter(this);
}

//控件初始化
private void init() {
et_username = (EditText)findViewById(R.id.et_username);
et_password = (EditText)findViewById(R.id.et_password);
btn_login = (Button)findViewById(R.id.btn_login);
btn_login.setOnClickListener(this);
}

@Override
public void onClick(View v) {
username = et_username.getText().toString();
password = et_password.getText().toString();
Person person = new Person();
person.setUsername(username);
person.setPassword(password);
personPresenter.login(person);
}

@Override
void showPerson(String result){
Toast.makeText(this,result, Toast.LENGTH_SHORT).show();
}
}

3. MVVM

MV-VM相比与MVP就是将Presenter层替换成ViewModel层。ViewModel层所需要做的就是跟逻辑相关的代码,完全不会涉及到UI。谷歌针对MVVM架构推出了一款方便实现的工具–DataBinding。

在 DataBinding 库之前,我们经常会写一些重复性很高而且毫无营养的代码,比如:findViewById()、setText()、setOnClickListener() 等。直到2015谷歌 I/O大会推出了 DataBinding,一个实现视图和数据双向绑定的工具。使用 DataBinding 库以后,可以使用声明式布局文件来减少粘结业务逻辑和布局文件的代码,有利于开发者更方便地实现 MVVM 模式。

具体实现和配置方法参考这篇博客

工程目录示例:

Activity中绑定View Model,并在new ViewModel对象时中传入当前Activity对象,执行一系列业务逻辑。


总结:除了以上主流架构之外,还有一些分层架构等类型,都是开发者在实践过程中逐渐探索出的高效快速开发出APP的方法。熟悉APP架构能够帮助我们分析dex文件时大概把握开发者思路,从而提高分析效率。

参考文章:

【1】https://www.jianshu.com/p/01946d23d35b

【2】https://juejin.cn/post/6844903539341262855

【3】https://www.jianshu.com/p/153ba1adf4cc