【问题标题】:Android: Call ViewModel function with Data BindingAndroid:使用数据绑定调用 ViewModel 函数
【发布时间】:2019-04-20 12:11:39
【问题描述】:

我正在尝试使用数据绑定为片段中的按钮设置 onClick 侦听器。

每次按下“下一步”按钮时我都需要调用的函数位于视图模型中。

我设法将数据从视图模型绑定到我的布局 XML,但我仍然无法从视图模型调用函数:/

尝试调用 ViewModel 函数时出现此错误:

C:\Users\Michal\git\fitness-fatality\app\build\generated\source\kapt\debug\com\example\fitnessfatality\DataBinderMapperImpl.java:10: error: cannot find symbol
import com.example.fitnessfatality.databinding.FragmentWorkoutLoggingBindingImpl;
                                              ^
  symbol:   class FragmentWorkoutLoggingBindingImpl
  location: package com.example.fitnessfatality.databinding

我也尝试过像这样调用视图模型函数:

android:onClick="@{viewModel.incrementIndex()}"

但是,如果我绑定整个片段,我可以调用它的函数。

这就是我尝试使用视图模型实现点击绑定的方式:

<?xml version="1.0" encoding="utf-8"?>
<layout
        android:id="@+id/main_linear_container"
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto">

    <data>
        <import type="com.example.fitnessfatality.ui.workoutTracking.viewModels.TrackingViewModel"/>
        <import type="java.util.List"/>
        <import type="com.example.fitnessfatality.ui.workoutTracking.TrackingFragment" />
        <variable name="viewModel" type="TrackingViewModel" />
        <variable name="fragment" type="TrackingFragment" />
    </data>

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

//More layouts


                <Button
                        android:text="Next"
                        android:onClick="@{viewModel.incrementIndex}"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content" android:id="@+id/btn_next" android:layout_weight="1"/>
        </LinearLayout>
</layout>

在我的片段中我有

 private lateinit var trackingViewModel: TrackingViewModel

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        trackingViewModel = ViewModelProviders.of(this).get(TrackingViewModel::class.java)
    }

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
        val binding =
            DataBindingUtil.inflate<FragmentWorkoutLoggingBinding>(
                inflater,
                R.layout.fragment_workout_logging,
                container,
                false
            )

        binding.lifecycleOwner = this
        binding.viewModel = trackingViewModel
        binding.fragment = this

        return binding.root
    }

还有我的 ViewModel:

class TrackingViewModel(application: Application): BaseViewModel(application) {
    val workoutExercises: LiveData<List<WorkoutExercisePojo>>
    private val workoutExerciseRepository: WorkoutExerciseRepository

    val currentIndex: MutableLiveData<Int> = MutableLiveData()

    val index: LiveData<Int> = currentIndex

    init {
        val db = AppDatabase.getDatabase(application, scope)
        workoutExerciseRepository = WorkoutExerciseRepository(db.workoutExerciseDao())
        workoutExercises = workoutExerciseRepository.allWorkoutExercises
        currentIndex.value = 0
    }

    fun incrementIndex() {
        currentIndex.value = currentIndex.value!!.plus(1)
    }
}

【问题讨论】:

  • “我仍然无法从视图模型调用函数”——这是什么意思?你的症状是什么?我希望 @{viewModel.incrementIndex()} 的绑定表达式能够工作。
  • 当我尝试@{viewModel.incrementIndex()} 时,生成的文件中出现错误。我已经用错误消息更新了我的描述
  • “我在尝试调用 ViewModel 函数时遇到此错误”——如果您查看构建输出,您应该会收到与数据绑定布局资源相关的其他错误消息。
  • 我不是,我只是收到我在构建控制台中添加到描述中的错误

标签: android binding android-jetpack


【解决方案1】:

使用自定义 BindingAdapter:

@BindingAdapter("onClick")
fun onClick(view: View, onClick: () -> Unit) {
    view.setOnClickListener {
        onClick()
    }
}

你应该可以直接绑定一个viewmodel函数,比如

app:onClick="@{viewModel::forgotPasswordClicked}"

在您的 XML 中。这将导致一个 viewmodel 函数,如:

fun forgotPasswordClicked() {
    TODO("ForgotPasswordClicked")
}

这样,您也不必将不必要的 Android 依赖项导入到您的视图模型中。

【讨论】:

  • 最好使用android:onClick-"@{()-&gt;vm.yourFun()}",无需导入android类也无需创建绑定适配器
【解决方案2】:

设法解决了。问题是 ViewModel 中的 incremenetIndex 函数不接受 View 作为参数。

现在,ViewModel 中的函数如下所示:

fun incrementIndex(view: View) {
    currentIndex.value = currentIndex.value!!.plus(1)
}

【讨论】:

  • 从 XML 调用此函数时,您是如何传递 view 参数的?
  • 我不记得当时我是如何做到这一点的,但是如果您使用数据绑定,您可以在调用函数时从片段中传递视图,或者从 XML 布局中传递视图。您可能还想考虑拥有一个提供任何 UI 交互的界面。
猜你喜欢
  • 2020-09-21
  • 1970-01-01
  • 2014-03-28
  • 1970-01-01
  • 1970-01-01
  • 2019-06-01
  • 1970-01-01
  • 1970-01-01
  • 2017-12-16
相关资源
最近更新 更多