Android MVVM架构学习——ViewModel DataBinding

发布于:2024-04-12 ⋅ 阅读:(222) ⋅ 点赞:(0)

关于MVVM架构,我并不想花篇幅去做重复性的描述,网上一搜都是一堆讲解,大家可以自行了解,我所做的只是以最简单的例子,最有效的步骤,从零开始,去实现一个相对有点学习参考价值的项目。

先来看本文预计的实现效果

可以看到,就是一个非常简单的例子,当点击登录按钮之后,将用户输入的内容显示出来
接下来,将分步骤讲解如何以符合MVVM设计规范的代码来实现这个功能,重在展示如何从零开始,构建一个MVVM框架。

本文使用的开发环境:

         Android Studio Iguana | 2023.2.1 Patch 1

Gradle版本:

        gradle-8.4-bin.zip 

1.build.gradle文件(模块级)

1.1使用DataBinding
defaultConfig {
        ...
        buildFeatures {
            dataBinding = true
        }
        ...
    }
1.2 引用依赖
dependencies {

    implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0'
    implementation 'androidx.lifecycle:lifecycle-livedata:2.7.0'

}

 2.绘制布局

当我们新建项目或者是新建activity时,系统会默认为我们生成一个布局文件,如下

我们需要把默认布局改成DataBinding布局。选中根部局标签,按下Alt+Enter,在弹出的选项中,选择第一个Convert to data binding layout,系统会自动为我们修改布局

修改后的布局:

<?xml version="1.0" encoding="utf-8"?>
<!--使用databinding功能,根布局需要使用<layout>标签 -->
<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 Binding的<data>标签,用于定义布局中使用的数据对象和表达式-->
    <data>

    </data>

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


    </androidx.constraintlayout.widget.ConstraintLayout>

</layout>

3.Activity文件

/**
 * LoginActivity 类负责处理登录界面的逻辑。
 * 它扩展了 AppCompatActivity,并使用 DataBinding 和 ViewModel 来简化界面和数据的交互。
 */
public class LoginActivity extends AppCompatActivity {

    private ActivityLoginBinding binding; // 用于存放 DataBinding 实例
    private LoginViewModel viewModel; // 用于存放 LoginViewModel 实例

    /**
     * onCreate 方法在活动创建时被调用。
     * 它负责初始化界面、设置窗口边距和绑定数据。
     *
     * @param savedInstanceState 如果活动之前被销毁,这参数包含之前的状态。如果活动没被销毁之前,这参数是 null。
     */
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // 启用全面屏显示
        EdgeToEdge.enable(this);
        // 使用 DataBinding 来绑定布局
        binding = DataBindingUtil.setContentView(this, R.layout.activity_login);
        // 设置视图窗格的填充,以适应系统栏位的高度
        ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main), (v, insets) -> {
            Insets systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars());
            v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom);
            return insets;
        });
        // 创建并获取 LoginViewModel 实例
        viewModel = new ViewModelProvider(this).get(LoginViewModel.class);
        // 将 viewModel 绑定到布局上
        binding.setViewModel(viewModel);
        // 初始化监听器
        initListener();
    }

    /**
     * 初始化各种监听器,特别是登录按钮的点击事件。
     */
    private void initListener(){
        // 设置登录按钮的点击事件,收集用户输入并调用 viewModel 的 login 方法
        binding.btnLogin.setOnClickListener(v -> {
            viewModel.setAccount(binding.etAccount.getText().toString());
            viewModel.setPassword(binding.etPassword.getText().toString());
            viewModel.login();
        });
    }
}

4.定义ViewModel

比较好的编程规范是,每创建一个Activity/Fragment,都创建与其对应的ViewModel

/**
 * 登录视图模型类,用于管理登录相关的数据和逻辑。
 */
public class LoginViewModel extends ViewModel {

    // 账户名和密码的LiveData对象,用于在UI变化时通知订阅者
    private MutableLiveData<String> account = new MutableLiveData<>();
    private MutableLiveData<String> password = new MutableLiveData<>();

    /**
     * 获取账户名的LiveData对象。
     * @return 账户名的LiveData对象。
     */
    public MutableLiveData<String> getAccount() {
        return account;
    }

    /**
     * 获取密码的LiveData对象。
     * @return 密码的LiveData对象。
     */
    public MutableLiveData<String> getPassword() {
        return password;
    }

    /**
     * 设置账户名。
     * @param account 用户输入的账户名。
     */
    public void setAccount(String account) {
        this.account.postValue(account);
    }

    /**
     * 设置密码。
     * @param password 用户输入的密码。
     */
    public void setPassword(String password) {
        this.password.postValue(password);
    }

    /**
     * 执行登录操作,展示登录成功信息。
     * 该方法会将当前设置的账户名和密码通过Toast消息展示出来。
     */
    public void login(){
        //登录操作,例如demo中的展示Toast,但是展示Toast的操作应该放在View层执行,不可以在此处直接调用Toast!
    }

}

5.自定义Application

拆分ViewModel之后,将无法再从Activity中获取Context了,所以自定义Application,便于全局获取Context

public class MVVMApplication extends Application {

    private static MVVMApplication instance;

    public static MVVMApplication getInstance() {
        return instance;
    }

    @Override
    public void onCreate() {
        super.onCreate();
        instance = this;
    }
}

不要忘了manifest文件中声明一下

 <application
        android:name=".MVVMApplication"
...

网站公告

今日签到

点亮在社区的每一天
去签到