Android MVVM 架構(gòu)應(yīng)用實(shí)現(xiàn)

以前項(xiàng)目中雖然也使用MVVM架構(gòu),但由于整體框架不是我自己搭建的妻柒,導(dǎo)致我對(duì)于MVVM架構(gòu)的整體還是很不熟悉概耻,所以這次就自己搭建并實(shí)現(xiàn)一次MVVM架構(gòu)。

MVVM架構(gòu)使用的組件有ViewModel病往、LiveData、ViewBinding/DataBinding等骄瓣,這些組件都是Jetpack庫(kù)中的組件停巷。在使用ViewModel之前要先建立四個(gè)類別的概念:

  • ViewModelProcider.Factory:Factory用來生成ViewModel
  • ViewModel:持有LiveData,從Repository獲取數(shù)據(jù)榕栏,并向View提供數(shù)據(jù)
  • Repository:獲取和處理數(shù)據(jù)畔勤,可以從網(wǎng)絡(luò)、數(shù)據(jù)庫(kù)或其他API獲取并處理數(shù)據(jù)
  • LiveData:具有生命周期感知能力的可觀察的數(shù)據(jù)存儲(chǔ)器扒磁,通知View展示數(shù)據(jù)

下圖展示了MVVM架構(gòu)示意圖庆揪,以及相關(guān)組件在其中的作用。

MVVM架構(gòu)圖

了解了MVVM的基本架構(gòu)和其中各個(gè)組件的作用妨托,可以開始代碼實(shí)現(xiàn)了缸榛。我做這個(gè)項(xiàng)目的初衷是因?yàn)樽罱谡硎占疉ndroid常用的開源庫(kù),為了更方便的展示所實(shí)現(xiàn)的一個(gè)應(yīng)用兰伤。本項(xiàng)目使用Bmob直接作為后臺(tái)數(shù)據(jù)庫(kù)内颗,接入Bmob SDK后調(diào)用API可以直接獲取數(shù)據(jù),以此來模擬后臺(tái)接口敦腔。同時(shí)本項(xiàng)目使用Koin作為依賴注入的框架起暮,省去初始化ViewModel、Repository会烙、ViewModelProcider.Factory的過程。

先貼上項(xiàng)目目錄筒捺,需要關(guān)注的是高亮顯示的文件(使用Koin省去了Factory類的實(shí)現(xiàn)):

iShot2021-04-11 19.45.41
  1. ViewModel類:

    實(shí)現(xiàn)HomeViewModel類柏腻,需要繼承繼承自ViewModel(),作為HomeFragment的ViewModel系吭。HomeViewModel類的構(gòu)造參數(shù)是BmobRepository五嫂,類中有一個(gè)LiveData變量用來承載數(shù)據(jù),一個(gè)函數(shù)getAllRecommendLibrary()獲取開源庫(kù)數(shù)據(jù)肯尺,函數(shù)實(shí)現(xiàn)是repository在協(xié)程中獲取云數(shù)據(jù)庫(kù)中的數(shù)據(jù):

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

    實(shí)現(xiàn)BmobRepository類沃缘,作為HomeViewModel的數(shù)據(jù)提供方。BmobRepository類中有一個(gè)掛起函數(shù)getAllRecommendLibrary(libraryRecommendData: MutableLiveData<MutableList>)用來獲取云數(shù)據(jù)庫(kù)中的數(shù)據(jù)则吟,函數(shù)的參數(shù)是LiveData槐臀,在獲取數(shù)據(jù)后,利用setValue通知View展示數(shù)據(jù)氓仲。

    class BmobRepository {
        /**
         * 獲取Bmob中所有推薦開源項(xiàng)目
         */
        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")
                        }
                    }
                })
            }
        }
    }
    
    
  3. Koin初始化:

    Koin的初始化分為兩步:

    • 定義ViewModel水慨,告訴Kioin從哪里找到ViewModel和Repository并自動(dòng)生成得糜,這里我選擇直接寫在BaseApplication中,需要注意的是需要定義在最外層晰洒,即和Classt同級(jí):

    • 在Application的onCreate()函數(shù)中初始化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)
              }
          }
      }
      //第一步:
      //定義一個(gè)myModule作為Viewmodel
      val myModule = module {
          viewModel { HomeViewModel(get()) }
      }
      //定義一個(gè)repoModule
      val repoModel = module {
          single { BmobRepository() }
      }
      
      
  4. Fragment類實(shí)現(xiàn):

實(shí)現(xiàn)HomeFragment類作為視圖層朝抖,其中分為兩步:

  • 變量homeViewModel作為ViewModel獲取數(shù)據(jù),使用Koin后的初始化方式十分簡(jiǎn)單

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

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

        override fun onResume() {
            super.onResume()
            homeViewModel.getAllRecommendLibrary()
        }
    
    

自此,一個(gè)MVVM架構(gòu)的應(yīng)用搭建完成砌滞,第一次獨(dú)立的搭建MVVM架構(gòu)之后侮邀,對(duì)于MVVM架構(gòu)的理解加深了不少,對(duì)于JetPack庫(kù)中的組件和其它開源庫(kù)也有了新的認(rèn)識(shí)布持,此外MVVM架構(gòu)還經(jīng)常和Retrofit豌拙、RxJava等開源庫(kù)配合使用,希望以后有機(jī)會(huì)可以再進(jìn)行實(shí)踐操作L馀按傅!

本項(xiàng)目使用開源組件庫(kù):koin、timber胧卤、permissionx唯绍、BaseRecyclerViewAdapterHelper

視頻:Android中高級(jí)進(jìn)階之MVVM與JetPack

原文: https://juejin.cn/post/6949876356515627039

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市枝誊,隨后出現(xiàn)的幾起案子况芒,更是在濱河造成了極大的恐慌,老刑警劉巖叶撒,帶你破解...
    沈念sama閱讀 206,378評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件绝骚,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡祠够,警方通過查閱死者的電腦和手機(jī)压汪,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,356評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來古瓤,“玉大人止剖,你說我怎么就攤上這事÷渚” “怎么了穿香?”我有些...
    開封第一講書人閱讀 152,702評(píng)論 0 342
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)绎速。 經(jīng)常有香客問我皮获,道長(zhǎng),這世上最難降的妖魔是什么纹冤? 我笑而不...
    開封第一講書人閱讀 55,259評(píng)論 1 279
  • 正文 為了忘掉前任魔市,我火速辦了婚禮主届,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘待德。我一直安慰自己君丁,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,263評(píng)論 5 371
  • 文/花漫 我一把揭開白布将宪。 她就那樣靜靜地躺著绘闷,像睡著了一般。 火紅的嫁衣襯著肌膚如雪较坛。 梳的紋絲不亂的頭發(fā)上印蔗,一...
    開封第一講書人閱讀 49,036評(píng)論 1 285
  • 那天,我揣著相機(jī)與錄音丑勤,去河邊找鬼华嘹。 笑死,一個(gè)胖子當(dāng)著我的面吹牛法竞,可吹牛的內(nèi)容都是我干的耙厚。 我是一名探鬼主播,決...
    沈念sama閱讀 38,349評(píng)論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼岔霸,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼薛躬!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起呆细,我...
    開封第一講書人閱讀 36,979評(píng)論 0 259
  • 序言:老撾萬榮一對(duì)情侶失蹤型宝,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后絮爷,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體趴酣,經(jīng)...
    沈念sama閱讀 43,469評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,938評(píng)論 2 323
  • 正文 我和宋清朗相戀三年坑夯,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了岖寞。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,059評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡渊涝,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出床嫌,到底是詐尸還是另有隱情跨释,我是刑警寧澤,帶...
    沈念sama閱讀 33,703評(píng)論 4 323
  • 正文 年R本政府宣布厌处,位于F島的核電站鳖谈,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏阔涉。R本人自食惡果不足惜缆娃,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,257評(píng)論 3 307
  • 文/蒙蒙 一捷绒、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧贯要,春花似錦暖侨、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,262評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至宅广,卻和暖如春葫掉,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背跟狱。 一陣腳步聲響...
    開封第一講書人閱讀 31,485評(píng)論 1 262
  • 我被黑心中介騙來泰國(guó)打工俭厚, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人驶臊。 一個(gè)月前我還...
    沈念sama閱讀 45,501評(píng)論 2 354
  • 正文 我出身青樓挪挤,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親资铡。 傳聞我的和親對(duì)象是個(gè)殘疾皇子电禀,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,792評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容