mvvm的網路框架的搭建
之前,我們簡單的介紹了一下MVVM的框架的構成以及搭建的基本的demo 但是網路請求是我們日常開發當中,非常基本也是必須的一部分,下面 我們一起來梳理一下帶有網路請求的MVVM。
首先我們先在專案裡整合相關的依賴
/**
* 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',
databinding_version: '3.2.0-alpha10',
retrofit2_version : '2.3.0',
gson_version : '2.8.5',
rxandroid_version : '2.1.0',
rxjava_version : '2.2.2'
]
//*************************類庫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']
databindingLibs = [databinding: "com.android.databinding:compiler:$dependVersion.databinding_version"]
network = [
retrofit : "com.squareup.retrofit2:retrofit:$dependVersion.retrofit2_version",
retrofit_converters: "com.squareup.retrofit2:converter-gson:$dependVersion.retrofit2_version",
retrofit_adapters : "com.squareup.retrofit2:adapter-rxjava2:$dependVersion.retrofit2_version"]
gson = [gson: "com.google.code.gson:gson:$dependVersion.gson_version"]
rxandroid = [rxandroid: "io.reactivex.rxjava2:rxandroid:$dependVersion.rxandroid_version"]
rxjava = [rxjava: "io.reactivex.rxjava2:rxjava:$dependVersion.rxjava_version"]
//********************專案依賴列表**********************
kotlinDeps = [kotlin_base.values()]
supportDeps = [supportLibs.values()]
databindingDeps = [databindingLibs.values()]
networkDeps = [network.values(), gson.values()]
rxDeps = [rxandroid.values(), rxjava.values()]
}
複製程式碼
依賴的方式我們依舊採取這種統一管理的方式。 然後 我們在工程依賴
dependencies {
implementation fileTree(include: ['*.jar'], dir: 'libs')
implementation project.ext.kotlinDeps
implementation project.ext.supportDeps
implementation project.ext.networkDeps
implementation project.ext.rxDeps
annotationProcessor project.ext.databindingDeps
}
複製程式碼
程式碼實現
我們增加了一個remote的包 同時 增加了一個Service類 包的結構如圖
這個介面我們就從網上找了一個關於手機號的省份的api (想和Gsonfromat一樣把Json快速生成Kotlin的程式碼,推薦一個外掛JsonToKotlinClass)這樣就可以快速根據Json生成Kotlin的類,使用比較簡單和GsonFromat一樣的。 如圖 迅速生成了對應的實體。data class WeatherInfoData(
val weatherinfo: Weatherinfo
)
data class Weatherinfo(
val AP: String,
val Radar: String,
val SD: String,
val WD: String,
val WS: String,
val WSE: String,
val city: String,
val cityid: String,
val isRadar: String,
val njd: String,
val sm: String,
val temp: String,
val time: String
)
複製程式碼
現在開始寫請求
package yang.cehome.com.mvvmdemo.model.remote
import io.reactivex.Single
import retrofit2.http.GET
import yang.cehome.com.mvvmdemo.model.data.WeatherInfoData
/**
* @author yangzc
* @data 2018/9/11 18:13
* @desc WeatherService
*
*/
interface WeatherService {
//獲取天氣
@GET("/data/sk/101190408.html")
fun getWeatherInfo(): Single<WeatherInfoData>
}
複製程式碼
下面我們開始寫ViewModel
package yang.cehome.com.mvvmdemo.viewmodel
import android.databinding.ObservableField
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.schedulers.Schedulers
import yang.cehome.com.mvvmdemo.model.data.WeatherInfoData
import yang.cehome.com.mvvmdemo.model.remote.WeatherService
/**
* @author yangzc
* @data 2018/9/12 14:20
* @desc WeatherViewModel
*
*/
class WeatherViewModel(val remote: WeatherService) {
/******data******/
val weatherinfo = ObservableField<String>()
/******binding******/
fun loadWeather() {
remote.getWeatherInfo()
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe({ t: WeatherInfoData? ->
weatherinfo.set(t?.let { it.weatherinfo.toString() })
}, { t: Throwable? ->
weatherinfo.set(t?.message ?: "error")
})
}
}
複製程式碼
接下來 我們一起看一下Activity當中的程式碼
package yang.cehome.com.mvvmdemo.view
import android.databinding.DataBindingUtil
import android.os.Bundle
import android.support.v7.app.AppCompatActivity
import retrofit2.Retrofit
import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory
import retrofit2.converter.gson.GsonConverterFactory
import yang.cehome.com.mvvmdemo.R
import yang.cehome.com.mvvmdemo.databinding.ActivityMainBinding
import yang.cehome.com.mvvmdemo.model.data.Onclick
import yang.cehome.com.mvvmdemo.model.remote.WeatherService
import yang.cehome.com.mvvmdemo.viewmodel.OnclikViewModel
import yang.cehome.com.mvvmdemo.viewmodel.WeatherViewModel
/**
* MVVM 當中的一個V層 將三者聯絡起來
*/
class MainActivity : AppCompatActivity() {
private lateinit var mBinding: ActivityMainBinding
private lateinit var mViewMode: OnclikViewModel
private lateinit var mViewMode2: WeatherViewModel
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
val remote = Retrofit.Builder()
.baseUrl("http://www.weather.com.cn")
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.addConverterFactory(GsonConverterFactory.create())
.build().create(WeatherService::class.java)
mViewMode2 = WeatherViewModel(remote)
mBinding.vm = mViewMode
mBinding.remote = mViewMode2
}
}
複製程式碼
我們可以看到 在Activity當中承擔了請求網路的角色 但是 對於資料的處理並沒有在這裡體現,同時 我們可以看到對於點選的操作以及顯示並沒有出現在這裡。 接下來我再看一下佈局檔案,大家可以看到新的結構對於佈局檔案的重要性
<?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" />
<variable
name="remote"
type="yang.cehome.com.mvvmdemo.viewmodel.WeatherViewModel" />
</data>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".view.MainActivity">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="50dp">
<Button
android:id="@+id/bt_onclick"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="@{()->vm.click()}"
android:text="來點一下試試" />
<TextView
android:id="@+id/tv_count"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/bt_onclick"
android:layout_marginBottom="20dp"
android:text="@{vm.info}"
android:textSize="16sp"
tools:text="點了0次" />
</RelativeLayout>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="50dp"
android:layout_marginTop="60dp">
<Button
android:id="@+id/bt_load"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="@{()->remote.loadWeather()}"
android:text="網路獲取" />
<TextView
android:id="@+id/tv_load"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/bt_load"
android:layout_marginBottom="50dp"
android:text="@{remote.weatherinfo}"
android:textSize="16sp"
/>
</RelativeLayout>
</LinearLayout>
</layout>
複製程式碼
當然在最後別忘了加上網路許可權
<uses-permission android:name="android.permission.INTERNET" />
複製程式碼
接下來我們就可以看到效果了
至此完成了MVVM框架的搭建,也完成了基本的網路請求,對於MVVM框架有了一個更加深刻的瞭解,那麼接下來要進一步優化一下框架,豐富的功能。