MVVMLin一個基于Jetpack+Kotlin+協(xié)程+Retrofit的快速開發(fā)框架

MVVMLin

一個基于MVVM用Kotlin+Retrofit+協(xié)程+Databinding+LiveData來封裝的快速開發(fā)框架:
項目地址:MVVMLin

Github上關于MVVM的框架也不少,之前一直在用RxJava +Retrofit 用MVP模式來做項目,現(xiàn)在AndroidX 是大勢所趨,Kotlin已經(jīng)成官方語言兩年了,今年GoogleIO大會又出了新東西,哎~~~~學不動了呀。近期項目不太忙,把這幾個新東西結(jié)合起來,封裝了一個MVVM的框架,分享出來給大家獻丑了。
拋棄了強大的RxJava,心里還是有點虛的。

框架簡介

  • 使用技術
    基于MVVM模式用了 kotlin+協(xié)程+retrofit+livedata+DataBinding,默認使用了AndroidX
  • 基本封裝
    封裝了BaseActivity、BaseFragment、BaseViewModel基于協(xié)和的網(wǎng)絡請方式更加方便,考慮到有些小伙伴不太喜歡用DataBinding在xml中綁定數(shù)據(jù)的方式,也提供了相應的適配,兩種方式自行選擇。Retrofit2.6提供了對協(xié)程的支持,使用起來更加方便,不用考慮類型的轉(zhuǎn)換了。
  • 特點
    使用Rxjava 處理不好的話會有內(nèi)存泄露的風險,我們會用使用AutoDispose、RxLifecycle等方式來處理,但是使用協(xié)程來請求數(shù)據(jù),完全不用擔心這個問題,所有請求都是在viewModelScope中啟動,當頁面銷毀的時候,會統(tǒng)一取消,不用關心這個問題了。用Kotlin封裝,大量語法糖可使用。
  • 引入第三方庫
    AndroidUtilCode:包含了大量的常用工具類,簡直是必備神器啊。
    material-dialogs:彈窗
    glide:圖片加載
    Retrofit:網(wǎng)絡請求

1,如何使用

1.1 啟用databinding

在主工程app的build.gradle的android {}中加入:

dataBinding {
    enabled true
}

1.2 依賴

在主項目app的build.gradle中依賴

dependencies {
    ...
   implementation 'me.aleyn:MVVMLin:1.0'
}

或者 下載到本地導入Module

1.3 配置依賴版本文件 config.gradle

復制Demo的 config,gradle 到要目錄,在項目的build.gradle 中加入:

apply from: "config.gradle"

2,快速開始

2.1Activity

繼承BaseActivity

class DetailActivity : BaseActivity<NoViewModel, ViewDataBinding>() {
    override fun layoutId() = R.layout.activity_detail
    
    override fun initView(savedInstanceState: Bundle?) {
       ....
    }

    override fun initData() {
      ....
    }
}

第一個泛型是VIewModel,如果頁面很簡單不需要ViewModel,直接傳入NoViewModel即可。
第二個泛型是Databinding,如果頁面使用Databinding的話,就要傳對應生成的Binding類,如果這個頁面不使用DataBinding,傳ViewDataBinding,基類不會初始化mBinding而會使用setContentView(l)方式。
layoutId() 方法返回對應布局
initView()initData() 為默認實現(xiàn),做初始化UI等操作

2.2 Fragment

繼承BaseFragment

class HomeFragment : BaseFragment<HomeViewModel, ViewDataBinding>() {
        override fun layoutId() = R.layout.home_fragment
        override fun initView(savedInstanceState: Bundle?) {  }
        override fun lazyLoadData() { 
            ....
        }
}

實現(xiàn)方法同Activity一樣,F(xiàn)ragment多了懶加載方法lazyLoadData() 可選擇性重寫。
setUserVisibleHint() 方法已經(jīng)被棄用,懶加載使用新的方式實現(xiàn)。

同樣Fragment中如果想不使用Databinding,泛型傳ViewDataBinding

2,使用DataBinding,布局文件:

<layout>
    <data>
    .....
    </data>
    .....
</layout>

泛型傳對應生成Binding類:

class ProjectFragment : BaseFragment<ProjectViewModel, ProjectFragmentBinding>() {
        .........
}
2.3 ViewModel

繼承BaseViewModel

class HomeViewModel : BaseViewModel() {
        .........
}

如果一個頁面內(nèi)容很少,不需要ViewModel,我們可能不想再建一個ViewModel類,泛型傳NoViewModel即可。
BaseVIewModel 中對協(xié)程進行了簡單封裝,BaseViewMode 已經(jīng)做了對網(wǎng)絡請求異常的統(tǒng)一處理。比如我們的網(wǎng)絡請求可以這樣寫:

class HomeViewModel : BaseViewModel() {
    private val homeRepository by lazy { InjectorUtil.getHomeRepository() }
    val mBanners = MutableLiveData<List<BannerBean>>()
    fun getBanner() {
        //只返回結(jié)果,其他全拋自定義異常
        launchOnlyresult({ homeRepository.getBannerData() }, {
            mBanners.value = it
        })
    }
}

那如果我們想自己處理錯誤怎么辦?

class HomeViewModel : BaseViewModel() {
    private val homeRepository by lazy { InjectorUtil.getHomeRepository() }
    val mBanners = MutableLiveData<List<BannerBean>>()
    fun getBanner() {
        launchOnlyresult({ homeRepository.getBannerData() }, {
            mBanners.value = it
        },{
         // 這里是Error 返回   ()
        })
    }
}

只需要加一個方法參數(shù)就行了。

另一種不過濾返回結(jié)果的方式:

class MeViewModel : BaseViewModel() {
    private val homeRepository by lazy { InjectorUtil.getHomeRepository() }
    var popularWeb = MutableLiveData<List<UsedWeb>>()
    fun getPopularWeb() {
        launch({
            val result = homeRepository.getPopularWeb()  //
            if (result.isSuccess()) {
                popularWeb.value = result.data
            }
        })
    }
}

要自己處理Error 跟上面一樣,加一個方法參數(shù)就行了。

每個網(wǎng)絡請求都會加等待框,如果我們不想要等待框:

 fun getProjectType() {
        launchOnlyresult({
            homeRepository.getNaviJson()
        }, {
            navData.addAll(it)
            it.forEach { item ->
                navTitle.add(item.name)
            }
        }, isShowDialog = false)
 }

isShowDialog 傳false,默認是true

3,例子

Demo中只展示了三種列表使用方式

3.1 不使用Databinging,結(jié)合BRVAH

詳見Demo的 HomeFragment

3.2 使用Databinging,結(jié)合bindingcollectionadapter

結(jié)合bindingcollectionadapter不用寫Adapter適配器了,詳見Demo的 ProjectFragment

3.2 使用Databinging,結(jié)合BRVAH

BRVAH 對DataBinding也做了支持,詳見Demo的 MeFragment

4,關于框架

剛剛完成1.0版,也算是我對新東西的一個學習過程,問題應該還是挺多的,后續(xù)會進一步完善,下一步會考慮把Eventbus加進去,也歡迎大家多提意見。順手給個Stat。哈哈~~~~~~

最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容