Android MVVM架構搭建

以前項目中雖然也使用MVVM架構,但由于整體框架不是我自己搭建的,導致我對于MVVM架構的整體還是很不熟悉,所以這次就自己搭建并實現一次MVVM架構。

MVVM架構使用的組件有ViewModel、LiveData、ViewBinding/DataBinding等,這些組件都是Jetpack庫中的組件。在使用ViewModel之前要先建立四個類別的概念:

  • ViewModelProcider.Factory:Factory用來生成ViewModel
  • ViewModel:持有LiveData,從Repository獲取數據,并向View提供數據
  • Repository:獲取和處理數據,可以從網絡、數據庫或其他API獲取并處理數據
  • LiveData:具有生命周期感知能力的可觀察的數據存儲器,通知View展示數據

下圖展示了MVVM架構示意圖,以及相關組件在其中的作用。


MVVM架構圖

了解了MVVM的基本架構和其中各個組件的作用,可以開始代碼實現了。我做這個項目的初衷是因為最近在整理收集Android常用的開源庫,為了更方便的展示所實現的一個應用。本項目使用Bmob直接作為后臺數據庫,接入Bmob SDK后調用API可以直接獲取數據,以此來模擬后臺接口。同時本項目使用Koin作為依賴注入的框架,省去初始化ViewModel、Repository、ViewModelProcider.Factory的過程。

先貼上項目目錄,需要關注的是高亮顯示的文件(使用Koin省去了Factory類的實現):

文件目錄
  1. ViewModel類:

    實現HomeViewModel類,需要繼承繼承自ViewModel(),作為HomeFragment的ViewModel。HomeViewModel類的構造參數是BmobRepository,類中有一個LiveData變量用來承載數據,一個函數getAllRecommendLibrary()獲取開源庫數據,函數實現是repository在協程中獲取云數據庫中的數據:

 class HomeViewModel(private val repository: BmobRepository) : ViewModel() {
         var libraryRecommendData = MutableLiveData<MutableList<AndroidLibrary>>()
     
         fun getAllRecommendLibrary() {
             viewModelScope.launch {
                 repository.getAllRecommendLibrary(libraryRecommendData)
            }
        }
     }
  1. Repository類:

    實現BmobRepository類,作為HomeViewModel的數據提供方。BmobRepository類中有一個掛起函數getAllRecommendLibrary(libraryRecommendData: MutableLiveData<MutableList<AndroidLibrary>>)用來獲取云數據庫中的數據,函數的參數是LiveData,在獲取數據后,利用setValue通知View展示數據。

class BmobRepository {
         /**
          * 獲取Bmob中所有推薦開源項目
          */
         suspend fun getAllRecommendLibrary(libraryRecommendData: MutableLiveData<MutableList<AndroidLibrary>>) {
             return withContext(Dispatchers.IO) {
                 val bombQuery: BmobQuery<AndroidLibrary> = BmobQuery()
                 bombQuery.findObjects(object : FindListener<AndroidLibrary>() {
                     override fun done(data: MutableList<AndroidLibrary>?, ex: BmobException?) {
                         if (ex == null) {
                             Timber.d("Bmob find success")
                             libraryRecommendData.value = data!!
                        } else {
                             Timber.d("Bmob exception $ex")
                        }
                    }
                })
            }
        }
     }
  1. Koin初始化:

    Koin的初始化分為兩步:

    • 定義ViewModel,告訴Kioin從哪里找到ViewModel和Repository并自動生成,這里我選擇直接寫在BaseApplication中,需要注意的是需要定義在最外層,即和Classt同級:

    • 在Application的onCreate()函數中初始化Koin:

class BaseApplication : Application() {
            override fun onCreate() {
                super.onCreate()
                //初始化Bmob
                Bmob.initialize(this, Constant.BMOB_APP_ID)
                //初始化Timber
                if (BuildConfig.DEBUG) {
                    Timber.plant(Timber.DebugTree())
                }
         
         //第二步:
                startKoin {
                    //Android context
                    androidContext(this@BaseApplication)
                    //modules
                    val list = listOf(myModule, repoModel)
                    modules(list)
                }
            }
         }
         //第一步:
         //定義一個myModule作為Viewmodel
         val myModule = module {
            viewModel { HomeViewModel(get()) }
         }
         //定義一個repoModule
         val repoModel = module {
            single { BmobRepository() }
         }
  1. Fragment類實現:
    實現HomeFragment類作為視圖層,其中分為兩步:
    • 變量homeViewModel作為ViewModel獲取數據,使用Koin后的初始化方式十分簡單

      private val homeViewModel: HomeViewModel by viewModel()//懶加載初始化
      
    • LiveData注冊監(jiān)聽ViewModel中的數據改變,并實現獲取數據后的操作

      private fun initRegister() {
                           //LiveData在視圖層中注冊監(jiān)聽后,在ViewModel中的數據改變時可以持續(xù)收到數據
                           homeViewModel.libraryRecommendData.observe(viewLifecycleOwner, {
                               Timber.d("t $it")
                              (binding.rvAndroidLibrary.adapter as AndroidLibraryAdapter).apply {
                                   data = it
                                   notifyDataSetChanged()
                              }
                          })
                      }
      
      • ViewModel調用函數通知Repository去查詢數據:
      override fun onResume() {
                           super.onResume()
                           homeViewModel.getAllRecommendLibrary()
                      }
      

自此,一個MVVM架構的應用搭建完成,第一次獨立的搭建MVVM架構之后,對于MVVM架構的理解加深了不少,對于JetPack庫中的組件和其它開源庫也有了新的認識,此外MVVM架構還經常和Retrofit、RxJava等開源庫配合使用,希望以后有機會可以再進行實踐操作?。?/p>

參考文章:Android MVVM 架構-使用 ViewModel、LiveData、Factory 以及 Repository

本項目源代碼android_all_star_app

本項目使用開源組件庫:koin、timber、permissionx、BaseRecyclerViewAdapterHelper

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

友情鏈接更多精彩內容