【原创】jetpack-LiveData实现双向绑定

2020-08-17  本文已影响0人  seekting

jetpack-LiveData实现双向绑定

先提一下使用androidx jetpack

gradle 6.1.1

distributionUrl=https\://services.gradle.org/distributions/gradle-6.1.1-all.zip

classpath

 dependencies {

        classpath 'com.android.tools.build:gradle:4.0.1'
        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"

        // NOTE: Do not place your application dependencies here; they belong
        // in the individual module build.gradle files
    }

app gradle

  lintOptions {
        checkReleaseBuilds false
        abortOnError false
    }
    buildFeatures {
        dataBinding true
    }

    compileOptions {
        coreLibraryDesugaringEnabled true
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }
dependencies {

    api "org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.2.0"
    coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.0.10'
}    

xml

<?xml version="1.0" encoding="utf-8"?>
<layout>

    <LinearLayout 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"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">


        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="@string/all_activity"
            />

        <EditText
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="@={mDBViewModel.username.firstName}" />
        <EditText
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="@={mDBViewModel.username.lastName}" />
        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="@={mDBViewModel.username.fullName}"
            />
        <EditText
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="@={mDBViewModel.pwd}" />

        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:onClick="@{()->mDBViewModel.clickLogin(@string/all_activity)}"

            />
    </LinearLayout>

    <data>

        <variable
            name="mUserName"
            type="String" />

        <variable
            name="mDBViewModel"
            type="com.seekting.demo2019.jetpack.DBViewModel" />
    </data>


</layout>

activity

package com.seekting.demo2019.jetpack

import android.app.Application
import android.os.Bundle
import android.text.TextUtils
import android.util.Log
import android.view.View
import androidx.appcompat.app.AppCompatActivity
import androidx.databinding.DataBindingUtil
import androidx.databinding.ObservableField
import androidx.lifecycle.*
import com.seekting.common.ToastUtils
import com.seekting.demo2019.DemoGroup
import com.seekting.demo2019.R
import com.seekting.demo2019.databinding.DbActivityBinding
import com.seekting.demo_lib.Demo

class UserName {

    var firstName = "zhang"
        set(value) {
            field = value
            setFullNameIn()
        }

    var lastName = "seekting"
        set(value) {
            field = value
            setFullNameIn()
        }

    var fullName = ObservableField("")

    private fun setFullNameIn() {
        fullName.set("$firstName.$lastName")

    }
}

class DBViewModel(application: Application) : AndroidViewModel(application) {

    var username: MutableLiveData<UserName>? = null
    var pwd: String = ""

    init {
        username = MutableLiveData<UserName>()

        username?.postValue(UserName())
        pwd = "zxt"
    }

    private fun checkLogin(): Boolean {
        if (TextUtils.equals(username?.value!!.fullName.get(), "zhang.seekting") && TextUtils.equals("zxt", pwd)) {

            return true
        }
        return false
    }

    fun login() {
        if (checkLogin()) {
            ToastUtils.showToast(getApplication(), "suc!")
            val old = username!!.value
            old?.firstName = "null"
            username?.postValue(old)
            pwd = "null"

        } else {
            ToastUtils.showToast(getApplication(), "username=${username?.value!!.fullName.get()} pwd=${pwd}")

        }

    }

    fun clickLogin(a: String) {
        login()
        Log.d("seekting", "DBViewModel.clickLogin()$a")

    }
}

@Demo(group = [DemoGroup.JETPACK])
class DBActivity : AppCompatActivity() {

    lateinit var mDbActivityBinding: DbActivityBinding
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        mDbActivityBinding = DataBindingUtil.setContentView(this, R.layout.db_activity)
        mDbActivityBinding.mdbViewModel =
                ViewModelProviders.of(this).get(DBViewModel::class.java)
        mDbActivityBinding.lifecycleOwner = this
        mDbActivityBinding.mdbViewModel?.username?.observe(this, object : Observer<UserName> {


            override fun onChanged(t: UserName?) {

            }

        })
    }
}

细节

达到双向绑定的要求:

  1. 使用LiveData
  2. 要加上mDbActivityBinding.lifecycleOwner = this
  3. EditText的更改导致user.firstName的更改,fullName也跟着更改,这时候FullNameTextView是不知道的,因为它不会user?.postValue(old)需要把fullName变成ObservableField
上一篇下一篇

猜你喜欢

热点阅读