MVVM的使用

本文详细介绍DataBinding的使用步骤及优化方法,并演示如何利用DataBinding实现MVVM模式,包括模型层、视图层和视图模型层的具体实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 

 

使用DataBinding需要三个步骤:

1、启用DataBinding

 2、修改布局文件为DataBinding布局

把传统的布局替换为dataBinding布局:在外层布局按住Ctrl+回车会提示是否转化成dataBinding布局,直接转化:

 3、数据绑定:替换setContentView: 经过上述步骤,系统会自动生成ActivityMainBinding类,类名是布局文件名+Binding,布局文件首字母大写

<?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"
    xmlns:tools="http://schemas.android.com/tools">

    <data>
        <variable
            name="account"
            type="com.example.myapplication.databinding.MyAccount" />
        <variable
            name="activity"
            type="com.example.myapplication.MainActivity" />
    </data>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        tools:context=".MainActivity">

        <TextView
            android:id="@+id/text_view"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@{account.name + '|' + account.level}"
            android:textSize="30dp"
            android:layout_gravity="center_horizontal"
            android:layout_marginTop="30dp" />

        <Button
            android:id="@+id/bt"
            android:layout_width="150dp"
            android:layout_height="wrap_content"
            android:text="加1"
            android:textSize="20dp"
            android:layout_gravity="center_horizontal"
            android:onClick="@{activity.onClick}"
            android:layout_marginTop="40dp" />
    </LinearLayout>
</layout>
public class MainActivity extends AppCompatActivity {
    ActivityMainBinding binding;
    MyAccount mAccount;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
//        setContentView(R.layout.activity_main);
        binding = DataBindingUtil.setContentView(this, R.layout.activity_main);
//        binding.textView.setText("你好");
        mAccount = new MyAccount();
        mAccount.setLevel("1");
        mAccount.setName("dongjie");
        binding.setAccount(mAccount);
        binding.setActivity(this);
    }

    public void onClick(View v) {
        Toast.makeText(this, "点击", Toast.LENGTH_LONG).show();
//        binding.setAccount(mAccount);
//        binding.textView.setText("aaaaa");
        mAccount = new MyAccount();
        mAccount.setLevel("2");
        mAccount.setName("dongjiejie");
        binding.setAccount(mAccount);
    }
}

经过上述步骤,修改数据就可以自动更新到界面上了。

上面的方法还可以优化,当数据变化的时候,自动更新界面数据:

1、继承BaseObservable

2、get方法添加@Bindable

3、set方法添加notifyPropertyChanged(BR.name);

package com.example.myapplication.databinding;

import androidx.databinding.BaseObservable;
import androidx.databinding.Bindable;

import com.example.myapplication.BR;

public class MyAccount extends BaseObservable {
    String name;
    String level;

    @Bindable
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
        // 当name发生变化的时候,更新界面数据, BR是DataBinding生成的,类似于R
        notifyPropertyChanged(BR.name);
    }

    @Bindable
    public String getLevel() {
        return level;
    }

    public void setLevel(String level) {
        this.level = level;
        notifyPropertyChanged(BR.level);
    }
}

经过上述步骤,上面的onClick方法就可以这么写:改变数据源以后会自动同步到界面上

    public void onClick(View v) {
        mAccount.setLevel("2");
        mAccount.setName("dongjiejie");
    }

到目前为止都是单向绑定,数据更新以后会直接同步到界面上,在@后面加等号就是双向绑定了,一般用的比较多得是输入框

MVVM实现需求需要以下几个步骤:

 下面给一个完整的demo: 

SecondActivity.java 和activity_second.xml

package com.example.myapplication.databinding2;

import androidx.appcompat.app.AppCompatActivity;
import androidx.databinding.DataBindingUtil;

import android.os.Bundle;

import com.example.myapplication.R;
import com.example.myapplication.databinding.ActivitySecondBinding;

public class SecondActivity extends AppCompatActivity {
    ActivitySecondBinding mBinding;
    MVVMViewModel mVVMViewModel;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mBinding = DataBindingUtil.setContentView(this, R.layout.activity_second);
        mVVMViewModel = new MVVMViewModel(getApplication(), mBinding);
        // 在xml里的变量都得初始化
        mBinding.setViewModel(mVVMViewModel);

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

    <data>
        <!-- 声明MVVMViewModel,在activity中初始化 -->
        <variable
            name="viewModel"
            type="com.example.myapplication.databinding2.MVVMViewModel" />
        <variable
            name="activity"
            type="com.example.myapplication.MainActivity" />
    </data>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        tools:context=".MainActivity">

        <EditText
            android:id="@+id/edit_view"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginLeft="30dp"
            android:layout_marginRight="30dp"
            android:textSize="30dp"
            android:text="@={viewModel.inputStr}"
            android:layout_marginTop="30dp" />

        <!--注意设置点击事件,不能带括号,只写方法名-->
        <Button
            android:id="@+id/bt"
            android:layout_width="150dp"
            android:layout_height="wrap_content"
            android:text="点击"
            android:textSize="20dp"
            android:layout_gravity="center_horizontal"
            android:onClick="@{viewModel.getData}"
            android:layout_marginTop="40dp" />

        <TextView
            android:id="@+id/text_view"
            android:textSize="20dp"
            android:textColor="#000"
            android:layout_marginTop="30dp"
            android:layout_gravity="center_horizontal"
            android:layout_width="match_parent"
            android:text="@{viewModel.result}"
            android:layout_height="wrap_content"/>
    </LinearLayout>
</layout>

MVVMViewModel.java

这一层相当于MVP的Presenter,处理逻辑,它里面调用Model层来请求数据,然后通过DataBinding来设置到界面上,如果遇到请求权限等操作,此层可以持有Activity的对象,或者用EventBus也可以, 不过一般不要这么做,一般用LiveData+ViewModel的方式来做。

package com.example.myapplication.databinding2;

import android.app.Application;
import android.view.View;

import androidx.databinding.BaseObservable;
import androidx.databinding.Bindable;

import com.example.myapplication.BR;
import com.example.myapplication.databinding.ActivitySecondBinding;

// MVVMViewModel相当于MVP的Presenter,处理业务逻辑
public class MVVMViewModel extends BaseObservable {
    Application application;
    ActivitySecondBinding mBinding;
    String result;
    String inputStr;
    MVVMModel mModel;
    public MVVMViewModel(Application application) {
        this.application = application;
        mModel = new MVVMModel();
    }

    public MVVMViewModel(Application application, ActivitySecondBinding binding) {
        this(application);
        mBinding = binding;
    }

    public void getData(View v) {
//        String editStr = mBinding.editView.getText().toString();
//        String ret = mModel.getScreenData(editStr);
//        setResult(ret);   // 必须调用setResult才能更新

        // 因为inputStr和控件是双向绑定,所以输入的时候inputStr是最新值,这样就不用传ActivitySecondBinding参数
        String ret = mModel.getScreenData(inputStr);
        setResult(ret);
    }

    @Bindable
    public String getResult() {
        return result;
    }

    public void setResult(String result) {
        this.result = result;
        notifyPropertyChanged(BR.result);
    }

    @Bindable
    public String getInputStr() {
        return inputStr;
    }

    public void setInputStr(String inputStr) {
        this.inputStr = inputStr;
        notifyPropertyChanged(BR.inputStr);
    }
}

MVVMModel.java     

这里模拟请求数据,一般是通过回调返回数据给MVVMViewModel的,这里为了简单写了同步方法

package com.example.myapplication.databinding2;

import com.example.myapplication.databinding.ActivitySecondBinding;

public class MVVMModel {
    public MVVMModel() {
    }

    public String getScreenData(String inputStr) {
        String str = "请求参数:" + inputStr + "\n请求数据:谢谢谢谢谢寻寻寻寻寻";
        return str;
    }
}
### 什么是MVVM架构模式 MVVM(Model-View-ViewModel)是一种用于分离用户界面逻辑和业务逻辑的软件架构模式。它将应用程序分为三个主要部分:模型(Model)、视图(View)和视图模型(ViewModel)。这种分离有助于提高代码的可维护性、可测试性和复用性[^1]。 ### WPF中实现MVVM的基本步骤 #### 1. 创建项目结构 在WPF项目中,通常会创建以下文件夹来组织代码: - **Model**:存放数据模型类。 - **ViewModel**:存放与UI交互的逻辑类。 - **View**:存放XAML文件及其代码隐藏文件。 #### 2. 定义Model 模型表示应用程序的数据层。例如,定义一个简单的数据类 `DataModel`: ```csharp namespace WPF0416.Model { public class DataModel { public int Value { get; set; } } } ``` #### 3. 创建ViewModel 视图模型负责处理视图的逻辑并与模型进行交互。使用 `GalaSoft.MvvmLight` 库中的 `ViewModelBase` 类可以轻松实现属性更改通知机制。 示例代码如下: ```csharp using GalaSoft.MvvmLight; using WPF0416.Model; namespace WPF0416.ViewModel { public class MonitorViewModel : ViewModelBase { private DataModel _dataModel; public MonitorViewModel() { _dataModel = new DataModel(); } private int _data; public int Data { get { return _data; } set { _data = value; RaisePropertyChanged(() => Data); } } public void UpdateData(int newValue) { Data = newValue; } } } ``` #### 4. 设计View 视图是用户界面的部分,通常通过绑定到视图模型的属性来显示数据。以下是一个简单的 XAML 文件示例: ```xml <Window x:Class="WPF0416.View.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="MainWindow" Height="350" Width="525"> <Grid> <StackPanel Orientation="Vertical" HorizontalAlignment="Center" VerticalAlignment="Center"> <TextBlock Text="Enter a number:" Margin="0,0,0,10"/> <TextBox x:Name="InputTextBox" Width="200" Height="30" Margin="0,0,0,10"/> <Button Content="Update" Command="{Binding UpdateCommand}" Margin="0,0,0,10"/> <TextBlock Text="{Binding Data}" FontSize="18"/> </StackPanel> </Grid> </Window> ``` #### 5. 绑定ViewModel到View 在 `App.xaml.cs` 或 `MainWindow.xaml.cs` 中设置视图模型为视图的数据上下文。例如: ```csharp using System.Windows; using WPF0416.ViewModel; namespace WPF0416.View { public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); DataContext = new MonitorViewModel(); } } } ``` #### 6. 实现命令绑定 为了响应用户操作(如按钮点击),可以在视图模型中定义命令。以下是使用 `RelayCommand` 的示例: ```csharp using GalaSoft.MvvmLight.Command; public class MonitorViewModel : ViewModelBase { // 其他代码... public RelayCommand<int> UpdateCommand { get; private set; } public MonitorViewModel() { _dataModel = new DataModel(); UpdateCommand = new RelayCommand<int>(UpdateData); } private void UpdateData(int newValue) { Data = newValue; } } ``` 在 XAML 中绑定命令时,可以通过传递参数来调用方法: ```xml <Button Content="Update" Command="{Binding UpdateCommand}" CommandParameter="{Binding ElementName=InputTextBox, Path=Text}"/> ``` ### 总结 上述示例展示了如何在WPF中实现MVVM架构模式。通过分离模型、视图和视图模型,可以显著提高代码的可维护性和可测试性。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值