You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android DataBinding获取EditText数据失败求助(新手)

问题核心

使用DataBinding实现EditText双向绑定时,ViewModel中的link变量始终为空,无法获取输入内容;同时对MutableLiveData、@Bindable的使用存在困惑,希望确认当前架构方向是否合理,并解决一个不影响运行的错误提示。


相关代码

XML布局文件(screen_main.xml)

<?xml version="1.0" encoding="utf-8"?>
<layout
    xmlns:android="http://schemas.android.com/apk/res/android"
    >
    <data>
        <variable
            name="viewmodel"
            type="com.example.myapplication.ui_logic.MainScreenLogic" />
    </data>
    <LinearLayout 
        android:orientation="vertical"
        android:layout_width="250dp"
        android:layout_height="wrap_content"
        android:stretchColumns="1">

        <TableRow
            android:layout_width="match_parent"
            android:layout_height="wrap_content">
            <TextView
                android:padding="3dip"
                android:text="@string/start" />
        </TableRow>
        <TableRow
            android:layout_width="match_parent"
            android:layout_height="wrap_content">
            <TextView
                android:padding="3dip"
                android:text="@string/destination" />
        </TableRow>
        <TableRow
            android:layout_width="match_parent"
            android:layout_height="wrap_content">
            <TextView
                android:padding="3dip"
                android:text="@string/time" />
        </TableRow>
        <TableRow
            android:layout_width="match_parent"
            android:layout_height="wrap_content">
            <TextView
                android:padding="3dip"
                android:text="@string/turns" />
        </TableRow>

        <TableRow
            android:layout_width="match_parent"
            android:layout_height="wrap_content">
            <EditText
                android:text="@={viewmodel.link}"
                android:id="@+id/link"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:background="@color/green"
                android:hint="@string/maps_link"
                android:inputType="text"
                android:minHeight="35dp"
                android:maxHeight="70dp"
                android:importantForAutofill="no">
                <requestFocus />
            </EditText>
        </TableRow>
    </LinearLayout>
</layout>

Main Activity代码

class Main_screen : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        val binding: ScreenMainBinding = DataBindingUtil.setContentView(this, R.layout.screen_main)
        val viewModel = ViewModelProvider(this)[MainScreenLogic::class.java]
        binding.viewmodel = viewModel
    }
}

ViewModel代码

package com.example.myapplication.ui_logic

import android.util.Log
import android.view.View
import androidx.databinding.Bindable
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel

class MainScreenLogic() : ViewModel() {
    var link = ""
    //val route = inputs(link)
    fun generateBt(view: View) {
        Log.d("button", link)
    }
}

Gradle依赖配置

plugins {
    id 'com.android.application'
    id 'org.jetbrains.kotlin.android'
    id 'org.jetbrains.kotlin.plugin.serialization'
}

android {
    namespace 'com.example.myapplication'
    compileSdk 34

    defaultConfig {
        applicationId "com.example.myapplication"
        minSdk 21
        targetSdk 33
        versionCode 1
        versionName "1.0"

        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
    }

    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }
    kotlinOptions {
        jvmTarget = '1.8'
    }
    dataBinding {
        enabled = true
    }
}

dependencies {
    def ktor_version = "2.3.2"
    implementation 'androidx.core:core-ktx:1.12.0-beta01'
    implementation 'androidx.appcompat:appcompat:1.6.1'
    implementation 'com.google.android.material:material:1.9.0'
    implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
    implementation 'androidx.core:core-ktx:1.12.0-beta01'
    implementation "io.ktor:ktor-client-core:$ktor_version"
    implementation "io.ktor:ktor-client-okhttp:$ktor_version"
    implementation "io.ktor:ktor-client-logging:$ktor_version"
    implementation "io.ktor:ktor-serialization-kotlinx-json:$ktor_version"
    implementation "org.jetbrains.kotlinx:kotlinx-serialization-core:1.5.1"
    implementation "androidx.lifecycle:lifecycle-extensions:2.2.0"
    implementation "androidx.activity:activity-ktx:1.7.2"
    implementation "androidx.fragment:fragment-ktx:1.5.7"
    testImplementation 'junit:junit:4.13.2'
    androidTestImplementation 'androidx.test.ext:junit:1.1.5'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'
}

解决方案

1. 修复双向绑定失效问题

当前问题核心:普通变量无数据变化通知机制,且未设置DataBinding生命周期所有者,导致双向绑定无法同步数据。推荐两种实现方式:

方式一:使用MutableLiveData(符合Jetpack架构规范)

修改ViewModel,用MutableLiveData存储可观察数据:

package com.example.myapplication.ui_logic

import android.util.Log
import android.view.View
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel

class MainScreenLogic : ViewModel() {
    // 用MutableLiveData实现可观察的双向绑定
    val link = MutableLiveData("")

    fun generateBt(view: View) {
        // 取值时判空避免空指针
        Log.d("button", link.value ?: "")
    }
}

修改Activity,添加生命周期所有者绑定:

class Main_screen : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        val binding: ScreenMainBinding = DataBindingUtil.setContentView(this, R.layout.screen_main)
        val viewModel = ViewModelProvider(this)[MainScreenLogic::class.java]
        binding.viewmodel = viewModel
        // 必须设置,让DataBinding感知生命周期,确保LiveData数据同步
        binding.lifecycleOwner = this
    }
}

XML无需修改,@={viewmodel.link}可直接与MutableLiveData双向绑定。

方式二:使用@Bindable和BaseObservable

若偏好普通变量,可实现Observable接口通知数据变化:

package com.example.myapplication.ui_logic

import android.util.Log
import android.view.View
import androidx.databinding.BaseObservable
import androidx.databinding.Bindable
import androidx.lifecycle.ViewModel
import com.example.myapplication.BR // BR类由DataBinding自动生成,需确保项目已编译

class MainScreenLogic : ViewModel(), BaseObservable() {
    @get:Bindable // 标记该属性可被DataBinding观察
    var link = ""
        set(value) {
            field = value
            // 通知DataBinding数据已更新
            notifyPropertyChanged(BR.link)
        }

    fun generateBt(view: View) {
        Log.d("button", link)
    }
}

Activity同样需要添加binding.lifecycleOwner = this。

2. 架构合理性确认

你采用的ViewModel + DataBinding方案符合Jetpack MVVM架构规范:

  • ViewModel负责持有数据和处理业务逻辑,与UI分离,可在配置变化(如旋转屏幕)时保留数据
  • DataBinding实现UI与数据的自动绑定,减少手动更新UI的代码
  • Activity仅负责初始化UI和绑定ViewModel,职责单一,易于维护

这个方向是正确的,后续可继续将业务逻辑(如你提到的inputs(link)方法)放在ViewModel或专门的Repository类中,进一步解耦。

3. 处理不影响运行的错误提示

常见非致命错误提示及解决方法:

  • 找不到BR类:执行Clean Project后Rebuild Project,DataBinding会自动生成BR类
  • XML中viewmodel类型报错:检查type属性的包名是否与MainScreenLogic实际包名一致
  • 依赖过时警告:lifecycle-extensions已废弃,替换为具体Lifecycle组件:
    // 移除旧依赖
    // implementation "androidx.lifecycle:lifecycle-extensions:2.2.0"
    // 添加新依赖
    implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.6.2"
    implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.6.2"
    

内容的提问来源于stack exchange,提问作者Red_button

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.14 14:18:11