MVVM框架的搭建(二)——项目搭建

介绍完背景以及初衷之后,我们开始搭建MVVM的框架,这一部分我们进行简单的搭建,了解MVVM架构的基本结构。

MVVM框架的搭建(一)——背景
MVVM框架的搭建(二)——项目搭建
MVVM框架的搭建(三)——网络请求
MVVM的数据持久化(一)——ROOM的集成
MVVM的数据持久化(二)——ROOM的使用

创建新项目

首先创建一个新的项目,在根目录下创建一个config.gradle如图


config.gradle用于配置项目中各种lib引用和版本号控制

/**
 * config.gradle用于配置项目中各种lib引用和版本号控制
 *
 * [module_*] 各module版本号及applicationId控制
 * 如需在各个module中升级更新版本号,请使用 module_[modulename]*的命名规则
 *
 * [project.ext.dependVersion] 中创建各个依赖库的版本号控制,需在类库名称后增加‘_version’
 *
 * [类库maven地址] 中创建各个类库的maven地址,同一类库需要引用多个类时,可以使用数组,要确保类库引用不重复
 *
 * [项目依赖列表] 中创建可以直接让module引用的依赖列表,以Deps结尾,原则上以类库功能分类,比如网络库,图片处理库
 * 尽量不要以类库本身的名字命名依赖列表
 *
 * 各个module中引用类库时尽量使用项目依赖列表中的项目,不要直接使用类库地址中的项目
 *
 * 需要添加新的类库时,先查询本列表和项目中是否已引用类似功能的类库,尽量不要添加重复功能的类库
 */
project.ext {
    compileSdkVersion = 27
    buildToolsVersion = '27.0.3'
    minSdkVersion = 16
    targetSdkVersion = 27

    //主app
    module_appApplicationId = 'yang.cehome.com.mvvmdemo'
    module_appVersionCode = 0001
    module_appVersionName = '1.0.0'
    module_appName = 'MVVM'

    //引用类库的版本号
    dependVersion = [
            kotlin_version : '1.2.51',
            support_version: '27.1.1'
    ]

    //*************************类库maven地址**************************
    kotlin_base = [kotlin_stdlib_jdk8: "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$dependVersion.kotlin_version"]
    supportLibs = [
            design      : "com.android.support:design:$dependVersion.support_version",
            appcompat_v7: "com.android.support:appcompat-v7:$dependVersion.support_version",
            constraint  : 'com.android.support.constraint:constraint-layout:1.1.3']
    //********************项目依赖列表**********************
    kotlinDeps = [kotlin_base.values()]
    supportDeps = [supportLibs.values()]
}

然后再build.gradle我们引用相应的library库



使用的时候需要注意的地方



依赖方法

AndroidStudio升级到3.0之后,gradle版本也随之升级到了3.0.0版本。
在这之后,大家可能注意依赖的方式发生了一些变化,在这里简单介绍一下


依赖方式

写在前面

现在MVC MVP MVVM框架的介绍很多,网上一搜一大堆就不着重介绍了。
之前用MVP重新写的框架,但是也遇到了很多不方便的地方,所以这次我们着重介绍MVVM框架
这里开始使用kotlin,并遵循google的App开发架构指南,才找到一种较好的构建MVVM应用程序的方式
首先:什么是MVVM?
MVVM是Model-View-ViewModel的简写,是有别于MVC和MVP的另一种架构模式。
相比于MVP,MVVM没有多余的回调,利用Databinding框架就可以将ViewModel中的数据绑定到UI上,从而让开发者只需要更新ViewModel中的数据,就可以改变UI。

再来讲一下分别的作用
● Model层:负责提供数据源给ViewModel,包含实体类,网络请求和本地存储等功能
● ViewModel:将Model层提供的数据根据View层的需要进行处理,通过DataBinding绑定到相应的UI上
● View:Activity、Fragment、layout.xml、Adapter、自定义View等等,负责将三者联系起来。

另一个好处就是可以做单元测试,纯的kotlin代码写着再舒服不过,而且可以保证数据的正确性。相比于run app需要十几秒或者几分钟、十几分钟,run 一次单元测试是以毫秒记的,效率是很可观的。

代码实现

首先我们创建一个类

/**
 * @author yangzc
 *  @data 2018/9/6 13:58
 *  @desc
 *
 */
class Onclick(val who: String, val count: Int)
以前我们写一个点击事件的代码大概
布局文件
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout 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"
    tools:context="yang.cehome.com.mvvmdemo.MainActivity">

    <Button
        android:id="@+id/bt_onclick"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="onclick"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <TextView
        android:id="@+id/tv_count"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginBottom="100dp"
        android:textSize="16sp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

</android.support.constraint.ConstraintLayout>
在Activity当中是这么实现的
package yang.cehome.com.mvvmdemo

import android.os.Bundle
import android.support.v7.app.AppCompatActivity
import android.view.View
import kotlinx.android.synthetic.main.activity_main.*

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        val onclik = Onclick("my", 0)
        tv_count.text = "${onclik.who}点击了${onclik.count}次"
        bt_onclick.setOnClickListener(View.OnClickListener {
            onclik.count++
            tv_count.text = "${onclik.who}点击了${onclik.count}次"
        })
    }
}

就实现了我们平时经常写的一段点击事件并且显示的一段代码
然而 我们要用MVVM框架显然就不是这么写的了 首先我们看一下架构



根据我们的这个结构图 我们简单阐述一下 各个模块的作用

Model层:负责提供数据源给ViewModel,包含实体类,网络请求和本地存储等功能
ViewModel层:将Model层提供的数据根据View层的需要进行处理,通过DataBinding绑定到相应的UI上
View层:Activity、Fragment、layout.xml、Adapter、自定义View等等,负责将三者联系起来
简单的介绍了一下MVVM之后,创建项目之后,看一下结构


包结构

基础Demo

下面我们就根据我们之前说的简单写一个Demo
首先看一下包的结构 DataBindingUtil.setContentView 这个函数做了三步操作:

  • inflate操作,创建布局文件对应的view对像
  • setContentView操作,将view加入window
  • bind操作,创建ActivityXxxBinding 对像 bind操作最终调用了ActivityXxxBinding.bind(view, bindingComponent)操作,然后调用了: new ActivityXxxBinding(bindingComponent, view) 创建了ActivityXxxBinding 对像。 //启用数据绑定 dataBinding{ enabled = true }
    我们看看布局文件 其实 我们可以看到在MVVM当中布局文件的作用有所加强,不仅仅是构造一个UI效果。
<?xml version="1.0" encoding="utf-8"?>
<layout 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">

    <data>
        <!--需要的viewModel,通过mBinding.vm=mViewMode注入-->
        <variable
            name="vm"
            type="yang.cehome.com.mvvmdemo.viewmodel.OnclikViewModel" />
    </data>

    <android.support.constraint.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".view.MainActivity">


        <Button
            android:id="@+id/bt_onclick"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:onClick="@{()->vm.click()}"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            tools:text="来点一下试试" />

        <TextView
            android:id="@+id/tv_count"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginBottom="100dp"
            android:text="@{vm.info}"
            android:textSize="16sp"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            tools:text="点了0次" />

    </android.support.constraint.ConstraintLayout>
</layout>

值得注意的几点:

1.最外层增加layout标签
2.增加了一个data标签 这个标签是我们的ViewModel通过绑定注入的
3.在每个控件上增加相应的方法
下面看看M层的代码 提供给ViewModel层的数据

package yang.cehome.com.mvvmdemo.model

/**
 * @author yangzc
 *  @data 2018/9/6 13:58
 *  @desc 数据源Model(MVVM 中的V),负责提供ViewModel中需要处理的数据
 *
 */
class Onclick(val who: String, var count: Int)

下面我们在看看ViewModel层 这里主要承担了数据处理功能 并负责提供给View层数据 ViewModel是用来存储和管理UI相关的数据。

package yang.cehome.com.mvvmdemo.viewmodel

import android.databinding.ObservableField
import yang.cehome.com.mvvmdemo.model.Onclick

/**
 * @author yangzc
 *  @data 2018/9/6 16:59
 *  @desc 处理数据V(MVVM 中的VM),负责提供View中需要处理的数据
 *
 */
class OnclikViewModel(val onlick: Onclick) {
    /******data******/
    val info = ObservableField<String>("\"${onlick.who}点击了${onlick.count}次\"")

    /******binding******/
    fun click() {
        onlick.count++
        info.set("\"${onlick.who}点击了${onlick.count}次\"")
    }

}

最后我们看看View层,也就是我们Activity和Fragment

package yang.cehome.com.mvvmdemo.view

import android.databinding.DataBindingUtil
import android.os.Bundle
import android.support.v7.app.AppCompatActivity
import yang.cehome.com.mvvmdemo.R
import yang.cehome.com.mvvmdemo.databinding.ActivityMainBinding
import yang.cehome.com.mvvmdemo.model.Onclick
import yang.cehome.com.mvvmdemo.viewmodel.OnclikViewModel

/**
 * MVVM 当中的一个V层 将三者联系起来
 */
class MainActivity : AppCompatActivity() {
    private lateinit var mBinding: ActivityMainBinding
    private lateinit var mViewMode: OnclikViewModel


    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        mBinding = DataBindingUtil.setContentView(this, R.layout.activity_main)
        /////model
        val onclick = Onclick("me", 0)
        ///ViewModel
        mViewMode = OnclikViewModel(onclick)
        ///binding
        mBinding.vm = mViewMode
    }
}

以上就是一个简单的MVVM的框架


实现效果

项目地址

https://github.com/yang0range/MVVM

欢迎关注公共号

关注公共号会有更多收获!

扫一扫,即刻加入到专属限免的星球当中,这里有很多有意思的人,好玩儿的事儿等待你!

扫一扫
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,417评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,921评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,850评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,945评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,069评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,188评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,239评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,994评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,409评论 1 304
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,735评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,898评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,578评论 4 336
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,205评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,916评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,156评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,722评论 2 363
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,781评论 2 351

推荐阅读更多精彩内容