使用EditText进行双向数据绑定

时间:2017-09-29 17:47:17

标签: android data-binding kotlin

我正在使用Kotlin开发一个简单的Android应用程序。我想使用数据绑定,但我无法使用EditText

这是我的XML布局

<?xml version="1.0" encoding="utf-8"?>
<layout
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        xmlns:app="http://schemas.android.com/apk/res-auto">
    <data>
        <import type="de.knerd.applicationmanager.models.AgencyModel"/>
        <variable name="agency" type="AgencyModel"/>
    </data>
    <RelativeLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            app:layout_behavior="@string/appbar_scrolling_view_behavior"
            tools:showIn="@layout/activity_add_agency"
            tools:context="de.knerd.applicationmanager.activities.AddAgencyActivity"
            android:orientation="vertical"
            android:layout_margin="16dp">
        <android.support.design.widget.TextInputLayout android:layout_height="match_parent"
                                                       android:layout_width="match_parent">
            <EditText
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:inputType="textPersonName"
                    android:ems="10"
                    android:id="@+id/name"
                    android:labelFor="@+id/name"
                    android:hint="@string/agency_name"
                    android:text="@={agency.name}"/>
        </android.support.design.widget.TextInputLayout>
    </RelativeLayout>
</layout>

这是我的Model类

package de.knerd.applicationmanager.models

import android.databinding.BaseObservable
import android.databinding.Bindable
import com.j256.ormlite.dao.ForeignCollection
import com.j256.ormlite.field.DatabaseField
import com.j256.ormlite.field.ForeignCollectionField
import com.j256.ormlite.table.DatabaseTable
import de.knerd.applicationmanager.BR

@DatabaseTable(tableName = "agency")
class AgencyModel : BaseObservable() {

    @DatabaseField(unique = true, canBeNull = false)
    @get:Bindable
    @set:Bindable
    var name: String? = null
        set(value) {
            field = value
            notifyPropertyChanged(BR.name)
        }
    @DatabaseField(generatedId = true)
    @get:Bindable
    var id: Int = 0
    @ForeignCollectionField(eager = false)
    @get:Bindable
    var agents: ForeignCollection<AgentModel>? = null
}

这是将模型绑定到视图的部分

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    binding = DataBindingUtil.setContentView<ContentAddAgencyBinding>(this, R.layout.content_add_agency)
    binding.agency = AgencyModel()
    setContentView(R.layout.activity_add_agency)
    val toolbar = findViewById(R.id.toolbar) as Toolbar
    setSupportActionBar(toolbar)
    supportActionBar!!.setDisplayHomeAsUpEnabled(true)
}

当我尝试访问绑定中的模型属性时,我得到一个空值。我使用的代码就是这个

private fun save(): Boolean {
    try {
        val agency = binding.agency
        Log.d("Name", agency.name)
        return true
    } catch (ex: Exception) {
        return false
    }
}

2 个答案:

答案 0 :(得分:1)

我发现了问题,这是由于我绑定到错误的布局造成的。正确的代码如下。

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    binding = DataBindingUtil.setContentView<ActivityAddAgencyBinding>(this, R.layout.activity_add_agency)
    binding.agency = AgencyModel()
    val toolbar = findViewById(R.id.toolbar) as Toolbar
    setSupportActionBar(toolbar)
    supportActionBar!!.setDisplayHomeAsUpEnabled(true)
}

在这两种情况下,我都必须绑定到活动布局

答案 1 :(得分:0)

你没有按照Knerd的方式使用Binding。双向绑定旨在使您可以从代码访问对象或字段,而无需引用UI代码。通过你执行binding.agency你和findViewById()没什么不同,你就是在破坏绑定的目的。

首先修复绑定问题。使用BaseObservable作为对象模型,它应该与屏幕上的任何值更改保持同步。

然后当你保存时,它应该只是访问本地变量。

private fun save(): Boolean {
    try {

        Log.d("Name", localObservableAgency.name)
        return true
    } catch (ex: Exception) {
        return false
    }
}

//不确定这个方法是什么,猜测你是尝试捕获null。更好的方法是对对象进行空检查,因为访问空值很重,并且不会增加值。此外,Kotlin是一种空的安全语言,所以你要么在绑定上失去你的价值,也可以通过将它设置为null来开始,或者在这里奇怪地编码一些东西,因为如果你保留一个本地副本,你必须故意使一个对象可以为空。但是,你并没有保留一个本地副本,你只需要新建一个内联副本,然后通过绑定访问,就好像它是你的变量存储库哈哈。

长话短说,使用数据绑定的方式是打算使用它并且你不会遇到问题。这可能就是为什么有人拒绝投票给你的原因。