Android 中的mvvm

来源:http://www.cnblogs.com/dyryy/archive/2016/12/29/6232825.html
-Advertisement-
Play Games

摘要:我們來瞭解一下MVVM模式與Databinding ,MVVM是一種模式,Databinding 是一種框架。DataBinding是一個實現數據和UI綁定的框架。而ViewModel和View可以通過DataBinding來實現單向綁定和雙向綁定,這套UI和數據之間的動態監聽和動態更新的框架 ...


摘要:我們來瞭解一下MVVM模式與Databinding ,MVVM是一種模式,Databinding 是一種框架。DataBinding是一個實現數據和UI綁定的框架。而ViewModel和View可以通過DataBinding來實現單向綁定和雙向綁定,這套UI和數據之間的動態監聽和動態更新的框架Google已經幫我們做好了。MVVM的思想和MVP類似。在MVVM模式中ViewModel和View是用綁定關係來實現的。

首先我們看一下mvvm中view、model、viewmodel三者是如何分工:

View簡單地說不做任何業務邏輯、不涉及處理數據、操作數據,把UI和數據分離。

Model: 實體模型,同時包括Retrofit 的Service ,ViewModel 可以根據Model 獲取一個Bean的Observable<Bean>( RxJava ),然後             做一些數據轉換操作和映射到ViewModel 中的一些欄位,最後把這些欄位綁定到View層上。

ViewModel負責完成View於Model間的交互,負責業務邏輯。ViewModel層做的事情剛好和View層相反,ViewModel 只做和業務邏輯和                 業務數據相關的事,不做任何和UI、控制項相關的事,ViewModel 層不會持有任何控制項的引用,更不會在ViewModel中通過UI                 控制項的引用去做更新UI的事情。ViewModel就是專註於業務的邏輯處理,操作的也都是對數據進行操作,這些個數據源綁定                   在相應的控制項上會自動去更改UI。記住:viewModel不做和UI相關的事。

我們在看看它的優勢:

  • 低耦合度:在MVVM模式中,數據是獨立於UI的,而ViewModel只負責處理和提供數據,UI想怎麼處理數據都是由UI自己決定的,ViewModel 不涉及任何和UI相關的事也不持有UI控制項的引用,即使控制項改變,ViewModel 幾乎不需要更改任何代碼。

  • 更新UI:在MVVM中,我們可以在工作線程中直接修改View Model的數據(只要數據是線程安全的),剩下的就不需要你去關心,數據綁定框架會幫我們搞定。

  • 可復用性:一個View Model復用到多個View中,同樣的一份數據,用不同的UI去做展示,對於版本迭代頻繁的UI改動,只需更換View層就行,對於如果想在UI上的做AbTest 更是方便的多。

  • 單元測試:View Model裡面是數據和業務邏輯,View中關註的是UI,這樣做測試是很方便的,完全沒有彼此的依賴,不管是UI的單元測試還是業務邏輯的單元測試,都是低耦合的。

view與viewmodel的協作:

Model 是通過Retrofit 去獲取網路數據的,返回的數據是一個Observable<Bean>( RxJava ),Model 層其實做的就是這些。那麼ViewModel 做的就是通過傳參數到Model層獲取到網路數據(資料庫同理)然後把Model的部分數據映射到ViewModel的一些欄位(ObservableField),併在ViewModel 保留這個Model的引用。

三者的關係:

 

 

 看完上面的圖,相信大家有了瞭解,接下來我們看看在代碼中的實現:

首先在項目里添加依賴:

     classpath 'com.android.tools.build:gradle:1.2.3'

     classpath 'com.android.databinding:dataBinder:1.0-rc0'

 

這裡用到 Data Binding,所以在Data Binding的模塊添加插件,在build里添加。

      apply plugin: 'com.android.databinding'

接下來我們看一下它的佈局文件:

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">

    <data>
        <variable
            name="viewModel"
            type="cn.saiz.mvvmhello.MainViewModel"/>
    </data>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="horizontal"
            android:layout_marginTop="10dp">
            <TextView
                android:layout_width="wrap_content"
                android:layout_height="match_parent"
                android:textSize="16sp"
                android:textColor="@android:color/black"
                android:gravity="center"
                android:text="用戶名:"/>
            <EditText
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:hint="simon"
                android:text="@={viewModel.userName}"
                app:addTextChangedListener="@{viewModel.userNameEditTextWatcher}"/>
        </LinearLayout>

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="horizontal"
            android:layout_marginTop="10dp">
            <TextView
                android:layout_width="wrap_content"
                android:layout_height="match_parent"
                android:textSize="16sp"
                android:textColor="@android:color/black"
                android:gravity="center"
                android:text="密碼:"/>
            <EditText
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:hint="123456"
                android:text="@={viewModel.passWord}"
                app:addTextChangedListener="@{viewModel.passwordEditTextWatcher}"/>
        </LinearLayout>

        <Button
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:onClick="@{viewModel.login}"
            android:text="登錄"/>

        <Button
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="註冊"/>
    </LinearLayout>
</layout>

相信大家看到了,我們的根節點變成了layout,還有一個data節點。

要實現 MVVM 的 ViewModel 就需要把數據與UI進行綁定,data 節點就為此提供了一個橋梁,我們先在data 中聲明一個 variable,這個變數會為 UI 元素提供數據(例如 TextView 的 android:text),然後在代碼中把”後臺”數據與這個 variable 進行綁定。

大家看一下variable

在 data 節點中聲明一個變數viewModel,這個name可以隨便起。其中 type 屬性就是我們在 Java 文件中定義的ViewModel 類。

在 build.gradle 中添加的那個插件 - com.android.databinding會根據xml文件的名稱 Generate一個繼承自 ViewDataBinding 的類。

例如,這裡 xml 的文件名叫 activity_main.xml,那麼生成的類就是 ActivityMainBinding

接下來我們綁定variable

@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        ViewDataBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_main);
        binding.setVariable(cn.saiz.mvvmhello.BR.viewModel, new MainViewModel(this));
    }

綁定之後,我們在佈局里就可以直接使用。看test

是不是很簡單,哈哈。

大家如果對mvvm感興趣,不妨可以深入研究一下,也可以把它跟mvp、mvc做一下對比。相信不久,你會愛上它的。

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 小程式裡面的轉換時間格式代碼 其實我最看重的是 ...
  • 屬於轉載 http status code:200:成功,伺服器已成功處理了請求,通常這表示伺服器提供了請求的網頁 404:未找到,伺服器未找到 201-206都表示伺服器成功處理了請求的狀態代碼,說明網頁可以正常訪問。 200(成功) 伺服器已成功處理了請求。通常,這表示伺服器提供了請求的網頁。 ...
  • 現在的css3真是強大,之前很多動畫都是用jq來實現,但是css3製作的動畫要比jq實現起來簡單很多,今天呢,我自己也寫了一個css旋轉動畫和大家分享。效果如下麵的圖片 思路:1.製作之前呢,我們先來整理一下思路,這個圓軸軌跡上一共有八個圓。 仔細看的話,你會發現一個規律,那就是一個月是360度的, ...
  • 前言 昨日,我請了一天假去考科目三,結果第一把掛在了沒完全關閉燈光上,第二把掛在轉彎時沒有觀察後方車輛,當聽到師傅一句“下去”的時候,我那是悲痛的面紅耳赤,這讓我很鬱悶,晚上也就不想回去上班了,回家後仍然有點低沉,在這種情況下,不寫點毒雞湯,好像已經不能好好的調節心情了,看看時間年底了,便寫寫今年的 ...
  • 學習 Activity 生命周期時希望通過 Dialog 主題測試 onPause() 和 onStop() 的區別。 點擊按鈕跳轉 Activity 時報錯: 找到最有用的一句話,說明所使用的 theme 和當前 Activity 不匹配。 AndroidManifest.xml 中 activi ...
  • 以下內容為原創,歡迎轉載,轉載請註明 來自天天博客: 使用Dagger 2進行依賴註入 Producers 原文: 本文是在Android中使用Dagger 2框架進行依賴註入的系列文章中的一部分。今天我們將探索下Dagger Producers 使用Java實現非同步依賴註入的Dagger2的一個擴 ...
  • 12.29日,小程式服務範圍做了重大更新,增對富媒體和工具類型的小程式,增加了很多細分領域 富媒體:增加資訊,FM電臺,有聲讀物等,媒體平臺可上小程式了 工具:信息查詢,網路代理,健康,企業管理等 ,更多查詢服務可以上線,企業辦公也可上了 商業服務:新增法律服務,不需要資格證書 ,線上法律咨詢可以上 ...
  • 由[OpenDigg](http://www.opendigg.com/) 出品的iOS開源項目周報第三期來啦。我們的iOS開源周報集合了OpenDigg一周來新收錄的優質的iOS開發方面的開源項目,方便iOS開發人員便捷的找到自己需要的項目工具等。 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...