MVVM 架構(gòu)演進(jìn)(一) —— 初探

一. 什么是 MVVM ?

MVVM 是前端一款數(shù)據(jù)驅(qū)動的架構(gòu)

  • Model: 網(wǎng)絡(luò)接口數(shù)據(jù), 本地緩存數(shù)據(jù)等
  • View: Activity, Fragment, DialogFragment.....
  • ViewModel: 提供數(shù)據(jù)源, 處理業(yè)務(wù)邏輯

二. MVVM 與 MVP 的區(qū)別是什么?

MVVM 與 MVP 十分的相似, MVVM 是從 MVP 架構(gòu)演進(jìn)而來的

  • MVP 通過 Presenter 做到了數(shù)據(jù)和視圖的解耦, 但是 Presenter 層的任務(wù)就變得十分之重, View 與 Presenter 交互要寫很多的接口, 接口粒度的控制也不容易把控
  • ViewModel 是為了解決 MVP 中 Presenter 過重這個問題而生的, ViewModel 和 View 之間的通信并不需要通過接口來回進(jìn)行數(shù)據(jù)導(dǎo)入導(dǎo)出, 而是通過注冊觀察者, 當(dāng)數(shù)據(jù)變更時會自動的反應(yīng)到與之綁定的 View 上

可以看到 MVVM 解決了 MVP 中最影響開發(fā)效率的一個環(huán)節(jié), 它可以使用更加整潔的代碼, 讓開發(fā)變的更加的高效

三. 如何使用 MVVM

一) Model

// 全局的數(shù)據(jù)倉庫
interface DataSource : LocalDataSource, RemoteDataSource {
    
    companion object {
        val INSTANCE: DataSource = DataRepository()
    }

}

// 唯一實現(xiàn)類
class DataRepository : DataSource

Model 層的設(shè)計非常簡單, 即一個全局的數(shù)據(jù)倉庫

二) View

1. Activity

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.main_activity)
        if (savedInstanceState == null) {
            supportFragmentManager.beginTransaction()
                .replace(R.id.container, MainFragment.newInstance())
                .commitNow()
        }
    }

}

Activity 為應(yīng)用殼, 布局也十分簡單, 直接填充了一個 Fragment

2. Fragment

class MainFragment : Fragment() {

    companion object {
        fun newInstance() = MainFragment()
    }

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View {
        // 這里 View 的創(chuàng)建交由 DataBinding 完成
        val dataBinding: MainFragmentBinding = MainFragmentBinding.inflate(inflater, container, false)
        // DataBinding 中持有 View 和 ViewModel 的引用, 他們直接的交互由 DataBinding 生成類 MainFragmentBinding 來控制
        dataBinding.view = this
        dataBinding.viewmodel = ViewModelProviders.of(this).get(MainViewModel::class.java)
        return dataBinding.root
    }

}

Fragment 中 View 的實例化非常的有趣, 它是通過 DataBinding 創(chuàng)建的, 并且通過 DataBinding 讓 View 層與 ViewModel 建立聯(lián)系, 這相當(dāng)于將 MVP 中 View 與 Presenter 的交互交由了系統(tǒng)控制

3. xml

<layout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tool="http://schemas.android.com/tools">

    <data>

        <import type="android.view.View"/>

        <variable
                name="view"
                type="com.sharry.demo.mvvm.ui.main.MainFragment"/>

        <variable
                name="viewmodel"
                type="com.sharry.demo.mvvm.ui.main.MainViewModel"/>
    </data>

    <androidx.constraintlayout.widget.ConstraintLayout
            android:id="@+id/main"
            android:layout_width="match_parent"
            android:layout_height="match_parent">

        <Button
                android:id="@+id/btnCenter"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:textAllCaps="false"
                android:text="@{viewmodel.messageText}"
                android:onClick="@{() -> viewmodel.messageClicked()}"
                app:layout_constraintBottom_toBottomOf="parent"
                app:layout_constraintEnd_toEndOf="parent"
                app:layout_constraintStart_toStartOf="parent"
                app:layout_constraintTop_toTopOf="parent"
                tool:text="I'm a fragment."
        />

    </androidx.constraintlayout.widget.ConstraintLayout>
</layout>

xml 中指定了 View 與 ViewModel, 并且讓控件的屬性直接與 ViewModel 中的數(shù)據(jù)綁定, 當(dāng) ViewModel 中數(shù)據(jù)變更后便會直接反應(yīng)到控件上去

三) ViewModel

class MainViewModel : ViewModel() {

    val messageText = ObservableField<String>()
    
    private val dataSource = DataSource.INSTANCE
     
    init {
        messageText.set("I'm a fragment.")
    }

    fun messageClicked() = messageText.set("Text changed by DataBinding.")

}

ViewModel 中的代碼也非常的簡單, 直接構(gòu)建了一些需要用的 ObservableXXX 類型的數(shù)據(jù), 讓其變更時, DataBinding 會直接通知 View 更新

UML 圖

image.png

四. 總結(jié)

從 MVVM 的示例實現(xiàn)上可知, DataBinding 在 MVVM 的架構(gòu)中起到了不可或缺的作用, 它將原本 MVP 中 View 與 Presenter 的交互轉(zhuǎn)移給了 DataBinding, 讓系統(tǒng)幫我們?nèi)ゾS護(hù)復(fù)雜的交互流程

優(yōu)勢

  • 開發(fā)者無需關(guān)心 ViewModel 與 View 的交互, 這一操作交由了 DataBinding 完成, 因此開發(fā)者可以更高效的進(jìn)行業(yè)務(wù)代碼的開發(fā)
  • ViewModel 與 View 之間沒有無依賴, 因此 ViewModel 的可移植性要大大的強(qiáng)于 Presenter

劣勢

  • 需要在 xml 中添加額外的代碼, 增加了額外的操作
  • View 數(shù)據(jù)的注入操作隱藏在 DataBinding 的生成類中, 增加了排查問題的難度
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末抡四,一起剝皮案震驚了整個濱河市柜蜈,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌指巡,老刑警劉巖淑履,帶你破解...
    沈念sama閱讀 207,113評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異藻雪,居然都是意外死亡秘噪,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,644評論 2 381
  • 文/潘曉璐 我一進(jìn)店門勉耀,熙熙樓的掌柜王于貴愁眉苦臉地迎上來指煎,“玉大人,你說我怎么就攤上這事便斥≈寥溃” “怎么了?”我有些...
    開封第一講書人閱讀 153,340評論 0 344
  • 文/不壞的土叔 我叫張陵枢纠,是天一觀的道長像街。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么宅广? 我笑而不...
    開封第一講書人閱讀 55,449評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮些举,結(jié)果婚禮上跟狱,老公的妹妹穿的比我還像新娘。我一直安慰自己户魏,他們只是感情好驶臊,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,445評論 5 374
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著叼丑,像睡著了一般关翎。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上鸠信,一...
    開封第一講書人閱讀 49,166評論 1 284
  • 那天纵寝,我揣著相機(jī)與錄音,去河邊找鬼星立。 笑死爽茴,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的绰垂。 我是一名探鬼主播室奏,決...
    沈念sama閱讀 38,442評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼劲装!你這毒婦竟也來了胧沫?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,105評論 0 261
  • 序言:老撾萬榮一對情侶失蹤占业,失蹤者是張志新(化名)和其女友劉穎绒怨,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體纺酸,經(jīng)...
    沈念sama閱讀 43,601評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡窖逗,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,066評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了餐蔬。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片碎紊。...
    茶點(diǎn)故事閱讀 38,161評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖樊诺,靈堂內(nèi)的尸體忽然破棺而出仗考,到底是詐尸還是另有隱情,我是刑警寧澤词爬,帶...
    沈念sama閱讀 33,792評論 4 323
  • 正文 年R本政府宣布秃嗜,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏锅锨。R本人自食惡果不足惜叽赊,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,351評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望必搞。 院中可真熱鬧必指,春花似錦、人聲如沸恕洲。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,352評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽霜第。三九已至葛家,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間泌类,已是汗流浹背癞谒。 一陣腳步聲響...
    開封第一講書人閱讀 31,584評論 1 261
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留末誓,地道東北人扯俱。 一個月前我還...
    沈念sama閱讀 45,618評論 2 355
  • 正文 我出身青樓,卻偏偏與公主長得像喇澡,于是被迫代替她去往敵國和親迅栅。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,916評論 2 344

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