使用Kotlin + JetPack 对旧项目进行MVVM改造
2020/5/17 23:26:21
本文主要是介绍使用Kotlin + JetPack 对旧项目进行MVVM改造,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
介绍
本次改造的项目地址为:github.com/stevenwsg/X…
这个项目是两年前在学校写的,当初写的时候比较赶时间,一直堆业务功能,没有考虑项目结构,写了很多重复代码。最近在看Kotlin协程和JetPack组件,就想着用Kotlin协程和JetPack组件对原项目进行重构。
MVVM
Android MVVM 架构图:
各层介绍:
- Model层,主要负责数据的提供。Model层提供业务逻辑的数据结构(比如,实体类),提供数据的获取(比如,从本地数据库或者远程网络获取数据),提供数据的存储。
- View层,主要负责界面的显示。View层不涉及任何的业务逻辑处理,它持有ViewModel层的引用,当需要进行业务逻辑处理时通知ViewModel层。
- ViewModel层,主要负责业务逻辑的处理。ViewModel层不涉及任何的视图操作。ViewModel层中数据的变化可以自动通知View层进行更新,因此ViewModel层不需要持有View层的引用。
Google JetPack搭建MVVM:
本次MVVM改造使用了JetPack的三个组件分别是:
- Lifecycles
- ViewModel
- LiveData
Lifecycles
作用:更方便的处理Android中生命周期的问题,它可以使你的组件具有感知生命周期的能力,从而根据生命周期状态来自动的响应一些动作。
使用文档:developer.android.com/topic/libra…
ViewModel
作用: 用来管理数据,它同样具有感知生命周期的能力,在宿主没有被销毁之前,数据不会丢失,且ViewModel不会重新创建,比如旋转屏幕等。同时,ViewMedel将数据从Activity中抽离出去,耦合度更低,更加方便维护。
使用文档:developer.android.com/topic/libra…
LiveData
配合ViewModel一起使用,存在于ViewModel中
LiveData 是一个可观测数据的容器类,与普通的可观测类不同,LiveData 能感知生命周期,并且只会在这些可观测的应用组件处于活动状态的时候才会更新它们,而且还会在与其关联的生命周期被销毁后自动清理自己。这样一来也就不会出现内存泄漏的问题了。
作用:底层数据改变时会自动更新UI,实际上我们可以看做是ViewModel于View之间通信的桥梁
使用文档:developer.android.com/topic/libra…
改造用户反馈模块
在项目中添加 lifecycle-extensions 和 Kotlin 依赖
implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0' implementation "androidx.core:core-ktx:1.2.0" implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.2.0" implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" 复制代码
下面是项目的结构:
- bean 反馈实体和请求返回实体
- model 存放业务逻辑相关
- view 存放Activity
- viewmodel 存放viewmodel相关类
在MVVM中,通过LiveData来实现ViewModel与View层之间的通信的,而且这个通信不是手动的,其核心是通过数据驱动的,也就是数据发生变化,view层会感知到并自动刷新ui。
1、View
View 持有ViewModel 的引用,当需要和Model进行通信时,通过ViewModel来进行通信。同时监听ViewModel中的数据变化,当ViewModel中的数据改变时,刷新UI,实现数据驱动。
class FeedBackActivity : BaseActivity() { private var mFeedBackVM : FeedBackViewModel? = null // 持有ViewModel的引用 override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_feedback) initView() initVM() initObserval() } private fun initView() { bt_back.setOnClickListener { if (!TextUtils.isEmpty(et_back.text.toString())) { mFeedBackVM?.getFeedBackMessage(et_back.text.toString()) // 调用ViewModel 的反馈方法, 解耦,单一职责 } else { Toasty.info(this@FeedBackActivity, getString(R.string.text_tost_empty), Toast.LENGTH_SHORT, true).show() } } } private fun initVM() { // 初始化ViewModel mFeedBackVM = ViewModelProviders.of(this).get(FeedBackViewModel::class.java) } private fun initObserval() { // 观测数据,当ViewModel的LiveData数据改变时,更新UI mFeedBackVM?.messageLiveData?.observe(this, Observer { t -> if (t?.code == 0) { Toasty.success(this@FeedBackActivity, t.message, Toast.LENGTH_SHORT, true).show() finish() } else { t?.message?.let { Toasty.error(this@FeedBackActivity, it, Toast.LENGTH_SHORT, true).show() } } }) } } 复制代码
2、ViewModel
ViewModel持有Model的引用,当View调用ViewModel请求数据时,ViewModel调用Model的方法。
class FeedBackViewModel : ViewModel() { var messageLiveData = MutableLiveData<FeedBackResultMessage>() // livedata用于驱动UI val mFeedBackModel = FeedBackModel() // 持有Model的引用 fun getFeedBackMessage(content: String) { // 调用Model的方法,将网络等异步操作放在Model中,便于Model单独测试 mFeedBackModel.feedBack(content, messageLiveData) } } 复制代码
3、Model
Model主要提供数据的请求和获取操作(缓存,数据库,网络等),并将结果赋值给ViewModel的LiveData, 实现数据驱动
class FeedBackModel { var feedBackResultMessage: FeedBackResultMessage? = null fun feedBack(content: String, liveData: MutableLiveData<FeedBackResultMessage>) { // livedata由ViewModel传入 GlobalScope.launch(Dispatchers.Main) { //使用协程进行异步操作 saveFeedBack(Feedback(content), liveData) // 网络请求操作 } } private suspend fun saveFeedBack(feedback: Feedback, liveData: MutableLiveData<FeedBackResultMessage>) = withContext(Dispatchers.IO) { feedback.save(object : SaveListener<String>() { override fun done(p0: String?, p1: BmobException?) { if (p1 === null) { feedBackResultMessage = FeedBackResultMessage(FeedBackResultMessage.CODE_SUCCESS, FeedBackResultMessage.MESSAGE_SUCCESS) liveData.postValue(feedBackResultMessage) // 子线程更新数据用postValue,数据驱动UI更新 } else { feedBackResultMessage = FeedBackResultMessage(FeedBackResultMessage.CODE_ERROR, FeedBackResultMessage.MESSAGE_ERROR) liveData.postValue(feedBackResultMessage) } } }) } } 复制代码
4、Bean
反馈实体
data class Feedback (var Content : String, var deviceType : String = "android", var userid : String = BmobUser.getCurrentUser(User::class.java).objectId) : BmobObject() //以前项目中使用了Bmob的数据库存储服务 复制代码
反馈结果实体
/* * code 0 代表成功 * code 1 代表失败 */ data class FeedBackResultMessage (val code : Int, val message: String) { companion object { const val CODE_SUCCESS : Int = 0 const val CODE_ERROR : Int = 1 const val MESSAGE_SUCCESS : String = "反馈成功~~~" const val MESSAGE_ERROR : String = "反馈失败~~~,请检查网络" } } 复制代码
总结
MVVM优点:
- 降低耦合度
- 数据驱动
- 可以异步线程更新数据
- 易于单元测试
- 方便协同开发等
目前已经使用这种改造方法改造了反馈模块,修改密码模块,发帖模块。后续的话逐渐把整个项目使用MMVM进行改造。
感兴趣的同学可以看看:github.com/stevenwsg/X…
这篇关于使用Kotlin + JetPack 对旧项目进行MVVM改造的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-01-18android.permission.read_media_video
- 2024-01-18android_getaddrinfo failed eai_nodata
- 2024-01-18androidmo
- 2024-01-15Android下三种离屏渲染技术
- 2024-01-09Android 蓝牙使用
- 2024-01-06Android对接华为AI - 文本识别
- 2023-11-15代码安全之代码混淆及加固(Android)
- 2023-11-10简述Android语音播报TTS
- 2023-11-06Android WiFi工具类
- 2023-07-22Android开发未来的出路