android程序结构改变了,基于Android的MVI架构:从双向绑定
到单向数据流
现在从事Android开发多少都要懂点架构知识,从MVC、MVP再到MVVM,想必⼤家对于其各⾃的优缺点早已如数家珍。今天介绍的MVI 与MVVM⾮常接近,可以针对性地弥补MVVM中的⼀些缺陷
何为MVI?
MVI即Model-View-Intent,它受Cycle.js前端框架的启发,提倡⼀种单向数据流的设计思想,⾮常适合数据驱动型的UI展⽰项⽬:
Model: 与其他MVVM中的Model不同的是,MVI的Model主要指UI状态(State)。当前界⾯展⽰的内容⽆⾮就是UI状态的⼀个快照:例如数据加载过程、控件位置等都是⼀种UI状态
View: 与其他MVX中的View⼀致,可能是⼀个Activity、Fragment或者任意UI承载单元。MVI中的View通
过订阅Intent的变化实现界⾯刷新(不是Activity的Intent、后⾯介绍)
Intent: 此Intent不是Activity的Intent,⽤户的任何操作都被包装成Intent后发送给Model进⾏数据请求
单向数据流
⽤户操作以Intent的形式通知Model => Model基于Intent更新State => View接收到State变化刷新UI。
数据永远在⼀个环形结构中单向流动,不能反向流动:
这种单向数据流结构的MVI有什么优缺点呢?
优点
UI的所有变化来⾃State,所以只需聚焦State,架构更简单、易于调试
数据单向流动,很容易对状态变化进⾏跟踪和回溯
state实例都是不可变的,确保线程安全
UI只是反应State的变化,没有额外逻辑,可以被轻松替换或复⽤
缺点
所有的操作最终都会转换成State,所以当复杂页⾯的State容易膨胀
state是不变的,每当state需要更新时都要创建新对象替代⽼对象,这会带来⼀定内存开销有些事件类的UI变化不适合⽤state描述,例如弹出⼀个toast或者snackbar
talk is cheap, show me the code。
我们通过⼀个Sample看⼀下如何快速搭建⼀个MVI架构的项⽬。
代码⽰例
代码结构如下:
Sample中的依赖库
// Added Dependencies
implementation "lerview:recyclerview:1.1.0" implementation 'android.arch.lifecycle:extensions:1.1.1' implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.2.0' implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.2.0' implementation 'com.github.bumptech.glide:glide:4.11.0'
//retrofit
implementation 'fit2:retrofit:2.8.1'
implementation "fit2:converter-moshi:2.6.2"
//Coroutine
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.6" implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.6"
复制代码
代码中使⽤以下API进⾏请求
复制代码
将得到结果:
1. 数据层
1.1 User
定义User的data class
del
data class User(
@Json(name = "id")
val id: Int = 0,
@Json(name = "first_name")
val name: String = "",
@Json(name = "email")
val email: String = "",
@Json(name = "avator")
val avator: String = ""
)
复制代码
1.2 ApiService
定义ApiService,getUsers⽅法进⾏数据请求
vi.data.api
interface ApiService{
@GET("users")
suspend fun getUsers(): List
}
复制代码
1.3 Retrofit
创建Retrofit实例
object RetrofitBuilder {
private const val BASE_URL = "reqres.in/api/user/1"
private fun getRetrofit() = Retrofit.Builder()
.baseUrl(BASE_URL)
.ate())
.build()
val apiService: ApiService = getRetrofit().create(ApiService::class.java) }
复制代码
1.4 Repository
定义Repository,封装API请求的具体实现
pository
class MainRepository(private val apiService: ApiService) {
suspend fun getUsers() = Users()
}
复制代码
2. UI层
Model定义完毕后,开始定义UI层,包括View、ViewModel以及Intent的定义
2.1 RecyclerView.Adapter
⾸先,需要⼀个RecyclerView来呈现列表结果,定义MainAdapter如下:
vi.ui.main.adapter
class MainAdapter(
private val users: ArrayList
) : RecyclerView.Adapter() {
class DataViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { fun bind(user: User) {
< = user.name
< = ail
Glide.with(t)
.load(user.avatar)
.into(itemView.imageViewAvatar)
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) = DataViewHolder(
LayoutInflater.t).inflate(
R.layout.item_layout, parent,
false
)
)
override fun getItemCount(): Int = users.size
override fun onBindViewHolder(holder: DataViewHolder, position: Int) = holder.bind(users[position])
fun addData(list: List) {
users.addAll(list)
}
android retrofit}
复制代码
l
xmlns:app="schemas.android/apk/res-auto"
xmlns:tools="schemas.android/tools"
android:id="@+id/container"
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论