预备知识
- 了解 Android 基本开发
看完本文可以达到什么程度
- 了解如何分析一个架构模式
- 掌握 MVC,MVP,MVVM 架构定义和实现
文章概览
一、什么是架构
关于架构的定义,其实在很多书籍和文章中都是不同的,很难做一个统一。这里列举两个定义:
在维基百科里是这样定义的:
软件架构是一个系统的草图。软件架构描述的对象是直接构成系统的抽象组件。各个组件之间的连接则明确和相对细致地描述组件之间的通讯。在实现阶段,这些抽象组件被细化为实际的组件,比如具体某个类或者对象。
在 IEEE 软件工程标准词汇中是这样定义的:
架构是以组件、组件之间的关系、组件与环境之间的关系为内容的某一系统的基本组织结构,以及指导上述内容设计与演化的原理。
关于更多的定义,推荐阅读《软件架构设计:程序员向架构师转型必备》第二章
...
在看过茫茫多的架构定义以后,我理解的架构是这样的:
- 为了解决特定的问题而提出
- 按照特定的原则将系统整体进行模块/组件/角色的划分
- 建立模块/组件/角色间的沟通机制
具体解释一下,首先是要有特定的问题,没有问题空谈架构,仿佛是空中楼阁,没有实用价值,而对应到不同的问题,会有不同的解决方式。
其次是模块的划分要根据特定的原则,没有原则随意划分,也就无从去评估一个架构的好坏。最后就是模块间的通信机制,让系统成为一个整体。
最后,架构模式,其实更多的是一种思想,一种规则,往往一种架构模式可能会有不同的实现方式,而实现方式之间,只有合适与否,并没有对错之分。
二、如何分析一种架构模式
上面我们介绍了架构的定义,根据这个定义,我们在后面分析架构模式的时候,也会从这三方面进行。
- 架构解决了什么问题
知道了架构模式要解决的问题,我们才能针对性的去看,去想其解决方法是否得当,是否合适。 - 架构模式是如何划分角色的
架构中最重要的就是角色 / 模块的划分,理解了架构模式中的角色划分,才能更好的理解其结构。 - 角色间是如何通信的
角色间的通信也是重要的。相同的角色划分,采用不同的通信方式,往往就构成了不同的架构模式。
角色间通信我们可以理解为数据的流向。在 Android 开发中,通信中的数据可以理解为两种,一种是数据结构,也就是网络请求,本地存储等通信使用的 JavaBean,另一种是事件,也就是控件产生的动作,包括触摸,点击,滑动等等。我们在通信过程中,也主要关注这两种数据。
三、常见的架构模式有哪些
对于我们 Android 开发者来说,常见的架构模式基本上就是 MVC,MVP,MVVM,这三种也是开发 GUI 应用程序常见的模式。
除此之外还有 分层模式,客户端-服务器模式(CS模式),主从模式,管道过滤器模式,事件总线模式 等等。
这篇文章还是具体分析 MVC,MVP,MVVM 这三种架构模式。
四、不使用架构之前 App 是怎么开发的
我们在了解架构的定义以后,可能会想,为什么要用这些架构模式呢?在我们不了解这些模式之前,也是一样的开发。类似设计模式,其实架构模式的目的不是为了让应用软件开发出来,而是让结构更清晰,分工更明确,扩展更方便等等。
我们可以看看,在不使用架构模式之前我们是怎么开发的。
举个简单的栗子,我们界面上有 EditText,TextView,Button 三个控件,要实现的功能也比较简单:
- EditText 接受用户输入的内容
- 处理用户输入的数据
- 数据处理后输出到 TextView 中
- 点击 Button 清空用户的输入
界面如下:
我们看看不使用架构模式是怎么开发的,也就是我们一般常用的开发方式:
- 首先在 xml 设计界面
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:padding="10dp"
tools:context=".MainActivity">
<TextView
android:id="@+id/titleText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Normal" />
<EditText
android:id="@+id/edit"
android:layout_width="match_parent"
android:layout_height="50dp"
android:textColor="@android:color/darker_gray" />
<TextView
android:id="@+id/msgText"
android:layout_width="wrap_content"
android:layout_height="30dp"
android:layout_marginTop="10dp"
android:text="default msg"
android:textColor="@android:color/darker_gray" />
<TextView
android:id="@+id/clearText"
android:layout_width="match_parent"
android:layout_height="30dp"
android:layout_marginTop="10dp"
android:background="@color/colorPrimary"
android:gravity="center"
android:text="clear"
android:textColor="@android:color/white" />
</LinearLayout>
- 在 Activity / Fragment 中获取 View,进行事件监听
- 通过 View 事件获取数据后进行处理
- 设置处理后的数据给 View 代码如下:
class NormalFragment : Fragment() {
companion object {
fun newInstance(): Fragment {
return NormalFragment()
}
}
private val handler: Handler = Handler()
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
return inflater.inflate(R.layout.architecture, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
titleText.text = "NORMAL"
edit.addTextChangedListener(object : TextWatcher {
override fun afterTextChanged(s: Editable?) {
handleData(s.toString())
}
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {