MVVM框架的搭建(二)——搭建
介紹完背景以及初衷之後,我們開始搭建MVVM的框架,這一部分我們進行簡單的搭建,瞭解MVVM架構的基本結構。
建立新專案
首先建立一個新的專案,在根目錄下建立一個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的框架