使用Android架构组件将单向数据绑定转换为双向数据绑定

使用Android架构组件将单向数据绑定转换为双向数据绑定,android,android-databinding,android-architecture-components,android-jetpack,two-way-binding,Android,Android Databinding,Android Architecture Components,Android Jetpack,Two Way Binding,我正在为一个大学项目重构我的Android应用程序,以使用架构组件,我很难在SwitchCompat上实现双向数据绑定。该应用程序有一个简单的用户界面,带有一个显示位置更新状态的TextView,以及前面提到的SwitchCompat,可以切换位置更新的开关。 目前,我在SwitchCompat的选中的属性上使用单向数据绑定,但希望使用。 使用模型-视图-模型体系结构的当前实现如下: MainViewModel.java: public class MainViewModel extends V

我正在为一个大学项目重构我的Android应用程序,以使用架构组件,我很难在
SwitchCompat
上实现双向数据绑定。该应用程序有一个简单的用户界面,带有一个显示位置更新状态的
TextView
,以及前面提到的
SwitchCompat
,可以切换位置更新的开关。
目前,我在
SwitchCompat
选中的
属性上使用单向数据绑定,但希望使用。
使用模型-视图-模型体系结构的当前实现如下:
MainViewModel.java

public class MainViewModel extends ViewModel {

    private LiveData<Resource<Location>> mLocationResource;

    public MainViewModel() {
        mLocationResource = Repository.getInstance().getLocationResource();
    }

    public LiveData<Resource<Location>> getLocationResource() {
        return mLocationResource;
    }

    public void onCheckedChanged (Context context, boolean isChecked) {
        if (isChecked) {
            Repository.getInstance().requestLocationUpdates(context);
        } else {
            Repository.getInstance().removeLocationUpdates(context);
        }
    }
}
android:onCheckedChanged="@{(buttonView, isChecked) -> viewModel.onCheckedChanged(context, isChecked)}"
android:checked="@{viewModel.getLocationResource}"
现在,
android:onCheckedChanged在fragment\u main.xml中实现了

public class MainViewModel extends ViewModel {

    private LiveData<Resource<Location>> mLocationResource;

    public MainViewModel() {
        mLocationResource = Repository.getInstance().getLocationResource();
    }

    public LiveData<Resource<Location>> getLocationResource() {
        return mLocationResource;
    }

    public void onCheckedChanged (Context context, boolean isChecked) {
        if (isChecked) {
            Repository.getInstance().requestLocationUpdates(context);
        } else {
            Repository.getInstance().removeLocationUpdates(context);
        }
    }
}
android:onCheckedChanged="@{(buttonView, isChecked) -> viewModel.onCheckedChanged(context, isChecked)}"
android:checked="@{viewModel.getLocationResource}"
最后是要从状态转换为布尔检查状态的自定义绑定适配器:

@BindingAdapter({"android:checked"})
public static void setChecked(CompoundButton view, Resource<Location> locationResource) {
    State state = locationResource.getState();
    boolean checked;
    if (state == State.STOPPED) {
        checked = false;
    } else {
        checked = true;
    }
    if (view.isChecked() != checked) {
        view.setChecked(checked);
    }
}
正如我上面链接的《Android开发者指南》所述,我如何才能在
Android:checked
中完成所有工作,而不是让
Android:checked
Android:onCheckedChanged
(单向数据绑定到双向数据绑定)?
另外,如果您认为我的应用程序的架构/逻辑可以改进,请告诉我:)

以下是我将如何做到这一点(很抱歉Kotlin代码):

首先,我将重构
资源
类,并使
状态
变量成为
MutableLiveData
对象:

enum class State {
    LOADING,
    UPDATE,
    UNKNOWN,
    STOPPED
}

class Resource<T>() {
    var state = MutableLiveData<State>().apply { 
        value = State.STOPPED //Setting the initial value to State.STOPPED
    }
}
就这样。现在:

  • 每当
    locationResource.state
    更改为
    state.STOPPED
    时,
    SwitchCompat
    按钮将变为未选中状态
  • 每当
    locationResource.state
    state.STOPPED
    更改为另一种状态时,
    SwitchCompat
    按钮将变为选中状态
  • 每当点击
    SwitchCompat
    按钮并更改为选中状态时,
    locationResource.state
    的值将更改为
    state.UPDATE
  • 每当点击
    SwitchCompat
    按钮并更改为未选中状态时,
    locationResource.state
    的值将更改为
    state.STOPPED

如果有什么不清楚的地方,请随时问我。

最后,我放弃了从单向数据绑定转换为双向数据绑定的尝试,但我设法简化了一点
android:checked
属性:
我取代了价值

"@{viewModel.getLocationResource}"


并完全删除了android:checked
@BindingAdapter

你好,Janosch谢谢你的回复。我不明白基于选中状态调用
requestLocationUpdates
removeLocationUpdates
的逻辑在哪里:它不应该在
resourceStateAttrChanged
BindingAdapter
中吗?我将您的应用程序转换为Java,并根据我的需要和假设进行编辑,但我得到了以下信息。(粘贴箱链接)。感谢您的帮助。Hm的
setResourceState(CompoundButton视图,int-state)
的状态参数不应该是
LocationState
类型的吗,
LocationState
是枚举吗?对于
public static int getResourceStateAttrChanged(CompoundButton视图)
的返回类型也是如此。错误看起来您仍然在使用函数
getLocationResource()
,并且您的
mLocationResource
仍然是一个LiveData对象,我建议您删除
getLocationResource()
将mLocationResource公开,并将其更改为带有可变LiveData对象
state
作为成员变量的资源,就像我回答的第一步一样。另外,在
public void onCheckedChanged(CompoundButton-buttonView,boolean-isChecked)方法中,您没有调用
attrChange.onChange()
。它通知数据绑定库开关的值已更改。至于在哪里调用requestLocationUpdates或removeLocationUpdates,这是另一个问题,但您的解决方案目前仍有效。嘿,又来了
LocationState
是一个包含
public static final int
s的类,我在看到后做了这个更改。是的,我仍然在使用
getLocationResource()
,因为我不想公开
mlLocationResource
,但我宁愿使用getter。另外,我希望保留
资源的结构
,而不是将
状态
字段设置为
可变livedata
。至于缺少的
attrChange.onChange()
,是的,它缺少是因为我需要基于选中状态请求/删除,并且因为我不知道双向数据绑定,正如标题所说,我将它扔到了那里。。。。。。如果您可以编辑您的答案,包括原始问题中
MainViewModel.java
中的
onCheckedChanged
逻辑,那将非常有用
"@{viewModel.getLocationResource}"
"@{viewModel.locationResource.state != State.STOPPED}"