Android 无法使用数据绑定从ViewModel与XML通信

Android 无法使用数据绑定从ViewModel与XML通信,android,mvvm,kotlin,data-binding,dagger,Android,Mvvm,Kotlin,Data Binding,Dagger,我正在尝试使用MVVM模式从xml与viewmodel通信,反之亦然。我以前从事过数据绑定工作,并成功地使用了Live Data-Dagger-MVVM。 最近,我尝试创建一个新项目,但从那时起,我无法使用XML和viewmodel跟踪响应。无论是从XML->ViewModel单击,还是从View->XML向文本视图赋值都不起作用。但并没有崩溃或任何事情,只是它不起作用。我已经添加了所有相关文件[MainActivity,activity\u main,viewModel,Dagger Modu

我正在尝试使用MVVM模式从xml与viewmodel通信,反之亦然。我以前从事过数据绑定工作,并成功地使用了Live Data-Dagger-MVVM。 最近,我尝试创建一个新项目,但从那时起,我无法使用XML和viewmodel跟踪响应。无论是从XML->ViewModel单击,还是从View->XML向文本视图赋值都不起作用。但并没有崩溃或任何事情,只是它不起作用。我已经添加了所有相关文件[MainActivity,activity\u main,viewModel,Dagger Module,build.gradle]

如果有人能告诉我这里出了什么问题,我将不胜感激

活动\u main.xml

<?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"
xmlns:tools="http://schemas.android.com/tools">

<data>
    <variable
        name="viewmodel"
        type="aveek.com.vm.ui.home.MainActivityViewModel"/>
</data>
<android.support.constraint.ConstraintLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

 <TextView

        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@{viewmodel.balanceText}"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        android:clickable="true"
        android:onClick="@{() -> viewmodel.clickData()}"
        app:layout_constraintTop_toTopOf="parent" />
...
</layout>
MainActivityViewModel.kt

class MainActivity : AppCompatActivity(),LifecycleOwner {

@Inject
lateinit var binding : ActivityMainBinding

override fun onCreate(savedInstanceState: Bundle?) {
    AndroidInjection.inject(this)
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)
    binding.setLifecycleOwner(this) 
    with(binding){
        this.viewmodel?.let {
            it.balanceText.set( "Aveek testing")
            it.data.observe(this@MainActivity, Observer {
                Toast.makeText(this@MainActivity, "Data is now : $it", Toast.LENGTH_SHORT).show()
            })
           }
         }
       }
class MainActivityViewModel : ViewModel() {
val data = MutableLiveData<Boolean>()
val balanceText = ObservableField<String>()
 fun clickData(){
    data.value = false
 }
}
@Module
class  MainActivityModule{

/**
 * provides binding to  Main Activity from respective XML
 * @property viewModel
 * @property context
 * @return binding of the view
 */
@Provides
fun binding(context: MainActivity, viewModel : MainActivityViewModel) : 
ActivityMainBinding {
    val binding = DataBindingUtil.setContentView<ActivityMainBinding>(context, 
    R.layout.activity_main)
    binding.viewmodel = viewModel
    return binding
 }
}
您将无法使用任何生成的方法将变量设置为绑定,因为除了ViewDataBinding之外没有公共超类,因此您将被迫使用反射,或者您可以使用方便的方法setVariable():


正如我所怀疑的,问题在于匕首注射。也许我用了一种错误的方法实现了viewmodel,但是如果在没有DI的情况下运行,viewmodel是非常好的

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)

    viewModel = ViewModelProviders.of(this).get(MainActivityViewModel::class.java)
    binding = DataBindingUtil.setContentView(this, R.layout.activity_main)
    binding.viewmodel = viewModel

    binding.setLifecycleOwner(this)
    mLifecycleRegistry = LifecycleRegistry(this).apply {
        markState(Lifecycle.State.CREATED)
    }
    with(binding){
        this.viewmodel?.let {
            it.balanceText.set( "Aveek testing")
            it.data.observe(this@MainActivity, Observer {
                Toast.makeText(this@MainActivity, "Data is now : $it", 
          Toast.LENGTH_SHORT).show()
            })
        }
    }
}
因此,我已经研究了DI代码,并在MainActivity.onCreate()中发现了这一点 我是这么做的

AndroidInjection.inject(this)
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
这基本上覆盖了数据绑定行为。所以我更新了如下代码

AndroidInjection.inject(this)
super.onCreate(savedInstanceState)
//setContentView(R.layout.activity_main)
// and initiated binding here as injecting binding from module before setting content won't be effective
val binding = DataBindingUtil.setContentView<ActivityMainBinding>(this, R.layout.activity_main)

现在它工作得非常好

在MainActivity中定义viewmodel的位置?我已经在模块中注入了带有绑定的viewmodel。您可以查看我上面附加的“MainActivityModule.kt”以供参考。尝试过了,仍然出现相同的问题。我想知道我的实现是否与dagger有任何问题。请在添加绑定后重试。executePendingBindings()行也不知道它应该如何工作,我认为您也尝试过,但只是说在清理项目后重试。没有DI就可以了,viewmodel及其行为工作良好。我已经添加了我的答案,你可以看一看。
AndroidInjection.inject(this)
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
AndroidInjection.inject(this)
super.onCreate(savedInstanceState)
//setContentView(R.layout.activity_main)
// and initiated binding here as injecting binding from module before setting content won't be effective
val binding = DataBindingUtil.setContentView<ActivityMainBinding>(this, R.layout.activity_main)
//    @Inject
//    lateinit var binding : ActivityMainBinding