前言
有一段时间没有去写过框架了,最近新的框架MVI,其实出来有一段时间了,只不过大部分项目还没有切换过去,对于公司的老项目来说,之前的MVC、MVP也能用,没有替换的必要,而对于新建的项目来说还是可以替换成功MVVM、MVI等框架的。本文完成后的效果图:
正文
每当一个新的框架出来,都会解决掉上一个框架所存在的问题,但同时也会产生新的问题,瑕不掩瑜,可以在实际开发中,解决掉产生的问题,就能够更好的使用框架,那么MVI解决了MVVM的什么问题呢?
MVI同样是基于观察者模式,只不过数据通信方面是单向的,解决了MVVM双向通信所带来的问题,实际上MVVM也能做成单向通讯,但是这样就不是纯粹的MVVM,当然了,仁者见仁,智者见智。MVI框架适用于UI变化很多的项目,通过数据去驱动UI,MVI就是Model、View、Intent。
- Model 这里的Model有所不同,里面还包含UI的状态。
- View 还是视图,例如Activity、Fragment等。
- Intent 意图,这个和Activity的意图要区分开,我觉得说成是行为可能更妥当,表示去做什么。
多说无益,我们还是进入实操环节吧。
一、创建项目
首先创建一个名为MviDemo的项目
项目创建好了,下面我们需要先进行项目的基本配置。
① 配置AndroidManifest.xml
文章中会通过一个网络API接口,拿到数据来进行MVI框架的搭建与使用,接口地址如下:
http://service.picasso.adesk.com/v1/vertical/vertical?limit=30&skip=180&adult=false&first=0&order=hot
通过浏览器打开可以得到很多数据,如图所示:
这些数据都是JSON格式的,后面我们还会用到这些数据。因为接口使用的是http,而不是https,所以在xml文件夹下新建一个network_security_config.xml,代码如下:
<?xml version="1.0" encoding="utf-8"?> <network-security-config> <base-config cleartextTrafficPermitted="true" /> </network-security-config>
然后在AndroidManifest.xml中的application标签中配置它,如图所示:
从Android 9.0起,默认使用https进行网络访问,如果要进行http访问则需要添加这个配置。还需要添加一个网络访问静态权限:
<uses-permission android:name="android.permission.INTERNET"/>
添加位置如下图所示:
项目正常搭建还需要一些依赖库和其他的一些设置,下面我们配置app模块下的build.gradle。
② 配置app的build.gradle
请注意,这里是配置app的build.gradle,而不是项目的build.gradle,很多人会配置错误,所以我再次强调一下,将你的项目切换到Android模式,如下图所示:
这里我标注了一下,你看到有两个build.gradle文件,两个文件的后面有灰色的文字说明,就很清楚的知道这两个build.gradle分别是项目和模块的。下面打开app模块下的build.gradle,在里面找到dependencies{}
闭包,闭包中添加如下依赖:
// lifecycle implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.4.1' implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.4.1' //glide implementation 'com.github.bumptech.glide:glide:4.14.2' //retrofit implementation 'com.squareup.retrofit2:retrofit:2.9.0' //retrofit moshi implementation "com.squareup.retrofit2:converter-moshi:2.6.2" //moshi used KotlinJsonAdapterFactory implementation "com.squareup.moshi:moshi-kotlin:1.9.3" //Coroutine implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.1" implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.1"
添加位置如下图所示:
然后再打开viewBinding,在android{}闭包下添加如下代码:
buildFeatures { viewBinding true }
添加位置如下图所示:
添加之后你会看到右上角有一个Sync Now,点击它进行依赖的载入配置,配置好之后进入下一步,为了确保你的项目没有问题,你可以现在运行一下看看。
二、网络请求
当我们使用Kotlin时,网络访问就变得更简单了,只需要Retrofit和协程即可,首先我们在com.llw.mvidemo
包下新建一个data
包,然后在data
包下新建一个model
包,model
包下我们可以通过刚才使用网页访问API拿到的JSON数据来生成一个数据类。
① 生成数据类
生成数据类,这里我们可以使用一个插件,搜索JSON To Kotlin Class,如下图所示:
下载安装之后,如果需要重启,你就重启AS,重启之后,右键点击model → New → Kotlin data class File from JSON,如图所示:
在出现的弹窗中复制通过网页请求得到的JSON数据字符串,如图所示:
这里如果觉得看起来不舒服,点击 Format 进行JSON数据格式化,然后我们需要设置数据类的名称,这里输入Wallpaper,因为我们需要使用Moshi,将JSON数据直接转成数据类,所以这里我们点击Advanced,如图所示:
这里默认是None,选择MoShi(Reflect),其他的不用更改,点击OK,此弹窗关闭,回到之前的弹窗,然后点击 Generate 生成数据类,你会发现有三个数据类,分别是Wallpaper、Res和Vertical,我们看一下Wallpaper的代码:
package com.llw.mvidemo.data.model import com.squareup.moshi.Json data class Wallpaper( @Json(name = "code") val code: Int, @Json(name = "msg") val msg: String, @Json(name = "res") val res: Res )
这里每一个字段上都有一个@Json
注解,这里是MoShi依赖库的注解,主要检查一下导包的问题,这里还有一个小故事,Google 的Gson库,算是推出比较早的,从事Gson库的开发人员,后面离职去了Square,也就是OkHttp、Retrofit的开发者。Retrofit一开始是支持Gson转换的,后面增加了MoShi的转换,Moshi拥有出色的Kotlin支持以及编译时代码生成功能,可以使应用程序更快更小。这个故事我也是听说的,你可以自己去求证,下面继续。
② 接口类
现在数据类有了,那么我们就需要根据这个数据类来写一个接口类,在com.llw.mvidemo
包下新建一个network
包,network
包下创建一个接口类ApiService
,代码如下所示:
interface ApiService { /** * 获取壁纸 */ @GET("v1/vertical/vertical?limit=30&skip=180&adult=false&first=0&order=hot") suspend fun getWallPaper(): Wallpaper }
这里属于Retrofit的使用方式,增加了协程的使用而已,就取代了RxJava的线程调度。
③ 网络请求工具类
现在有接口,下面我们来做网络请求,在network
包下新建一个NetworkUtils
类,代码如下:
package com.llw.mvidemo.network import com.squareup.moshi.Moshi import com.squareup.moshi.kotlin.reflect.KotlinJsonAdapterFactory import retrofit2.Retrofit import retrofit2.converter.moshi.MoshiConverterFactory /** * 网络工具类 */ object NetworkUtils { private const val BASE_URL = "http://service.picasso.adesk.com/" /** * 通过Moshi 将JSON转为为 Kotlin 的Data class */ private val moshi: Moshi = Moshi.Builder() .add(KotlinJsonAdapterFactory()) .build() /** * 构建Retrofit */ private fun getRetrofit() = Retrofit.Builder() .baseUrl(BASE_URL) .addConverterFactory(MoshiConverterFactory.create(moshi)) .build() /** * 创建Api网络请求服务 */ val apiService: ApiService = getRetrofit().create(ApiService::class.java) }
由于担心你看的时候导错包,现在贴代码我会将导包的信息也贴出来,这样你总不会再导错包了吧。下面简单说明一下这个类,首先我定义了一个常量BASE_URL。作为网络接口请求的地址头,然后构建了MoShi,通过MoShi去进行JSON转Kotlin数据类的处理,之后就是构建Retrofit,将MoShi设置进去,最后就是通过Retrofit创建一个网络请求服务。
Android MVI框架搭建与使用(下)https://developer.aliyun.com/article/1407599