kotlin构建MVVM应用之双向数据绑定

1,995 阅读2分钟

我们在构建MVVM应用的时候数据时双向流动的,比如:用户输入了数据,那么我们的model层的数据也要自动跟着更新或者我们校验了数据,是图层也要给用户反馈;网络请求完成,我们的视图层的数据也要跟着更新。

定义model层


package com.xiangshike.live.model

import androidx.databinding.ObservableField

data class UserModel(
    val username: ObservableField<String> = ObservableField(""),
    val password: ObservableField<String> = ObservableField("")
) {
    override fun toString(): String {
        return "UserModel(username=$username, password=$password)"
    }
}

ObservableField表示这是一个可以被观察的String类型数据,我们在用户的model层定义了两个可以被观察的变量,我们可以和视图进行双向绑定

Activity

package com.xiangshike.live

import android.util.Log
import com.xiangshike.live.base.BaseActivity
import com.xiangshike.live.databinding.ActivityMainBinding
import com.xiangshike.live.model.UserModel
import kotlinx.android.synthetic.main.activity_main.*

class MainActivity : BaseActivity<ActivityMainBinding>() {
    private val mUserModel: UserModel by lazy { UserModel() }
    override fun getLayoutId(): Int = R.layout.activity_main
    override fun initData() {
        mDataBind.userModel = mUserModel
    }

    override fun initView() {
        loginBtn.setOnClickListener {
            login()
        }
    }

    private fun login() {
        val username = mUserModel.username.get().toString()
        val password: String = mUserModel.password.get().toString()
        username.isEmpty().let {
            when (it) {
                true -> usernameLayout.error = "用户名不可以为空"
                false -> usernameLayout.isErrorEnabled = false
            }
        }
        password.isEmpty().also {
            when (it) {
                true -> passwordLayout.error = "密码不可以为空"
                false -> passwordLayout.isErrorEnabled = false
            }
        }

        Log.d("mUserModel", "username:$username  password:$password")
    }
}


首先,我们给登录按钮增加点击事件


    override fun initView() {
        loginBtn.setOnClickListener {
            login()
        }
    }

其次,我们定义了login的方法,在这里我们实现了视图和model的双向绑定


    private fun login() {
        val username = mUserModel.username.get().toString()
        val password: String = mUserModel.password.get().toString()
        username.isEmpty().let {
            when (it) {
                true -> usernameLayout.error = "用户名不可以为空"
                false -> usernameLayout.isErrorEnabled = false
            }
        }
        password.isEmpty().also {
            when (it) {
                true -> passwordLayout.error = "密码不可以为空"
                false -> passwordLayout.isErrorEnabled = false
            }
        }

        Log.d("mUserModel", "username:$username  password:$password")
    }

view层


<?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="userModel"
            type="com.xiangshike.live.model.UserModel" />
    </data>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">

        <com.google.android.material.textfield.TextInputLayout
            android:id="@+id/usernameLayout"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="66dp">

            <com.google.android.material.textfield.TextInputEditText
                android:id="@+id/username"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:hint="@string/username"
                android:singleLine="true"
                android:text="@={userModel.username}" />
        </com.google.android.material.textfield.TextInputLayout>

        <com.google.android.material.textfield.TextInputLayout
            android:id="@+id/passwordLayout"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="66dp"
            app:passwordToggleEnabled="true">

            <com.google.android.material.textfield.TextInputEditText
                android:id="@+id/password"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:hint="@string/password"
                android:inputType="textPassword"
                android:text="@={userModel.password}" />
        </com.google.android.material.textfield.TextInputLayout>

        <Button
            android:id="@+id/loginBtn"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="@string/login" />
    </LinearLayout>


</layout>

我们的用户名和model双向绑定

@={userModel.username} 实现的双向绑定,model<=>view的双向数据流通


    
    <com.google.android.material.textfield.TextInputEditText
        android:id="@+id/username"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="@string/username"
        android:singleLine="true"
        android:text="@={userModel.username}" />

我们输入内容,点击登录,查看控制台输出

2020-04-14 11:28:00.886 10583-10583/? D/mUserModel: username:1111  password:11111

链接:pan.baidu.com/s/1AKdt1qPk… 提取码:tphe