Android: 使用数据绑定调用 ViewModel 函数
Android: Call ViewModel function with Data Binding
我正在尝试使用数据绑定为片段中的按钮设置 onClick 侦听器。
每次按下 "next" 按钮时我需要调用的函数在视图模型中。
我设法将数据从视图模型绑定到我的布局 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 中的 incremenetIndex
函数不接受 View 作为参数。
所以现在,ViewModel 中的函数如下所示:
fun incrementIndex(view: View) {
currentIndex.value = currentIndex.value!!.plus(1)
}
使用自定义 BindingAdapter:
@BindingAdapter("onClick")
fun onClick(view: View, onClick: () -> Unit) {
view.setOnClickListener {
onClick()
}
}
您应该能够像
一样直接绑定视图模型函数
app:onClick="@{viewModel::forgotPasswordClicked}"
在你的 XML 中。这将导致像这样的视图模型函数:
fun forgotPasswordClicked() {
TODO("ForgotPasswordClicked")
}
这样,您也不必将不必要的 Android-依赖项导入您的视图模型。
我正在尝试使用数据绑定为片段中的按钮设置 onClick 侦听器。
每次按下 "next" 按钮时我需要调用的函数在视图模型中。
我设法将数据从视图模型绑定到我的布局 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 中的 incremenetIndex
函数不接受 View 作为参数。
所以现在,ViewModel 中的函数如下所示:
fun incrementIndex(view: View) {
currentIndex.value = currentIndex.value!!.plus(1)
}
使用自定义 BindingAdapter:
@BindingAdapter("onClick")
fun onClick(view: View, onClick: () -> Unit) {
view.setOnClickListener {
onClick()
}
}
您应该能够像
一样直接绑定视图模型函数app:onClick="@{viewModel::forgotPasswordClicked}"
在你的 XML 中。这将导致像这样的视图模型函数:
fun forgotPasswordClicked() {
TODO("ForgotPasswordClicked")
}
这样,您也不必将不必要的 Android-依赖项导入您的视图模型。