服务更新模型时的 MVVM 数据绑定

MVVM databinding when model is updated by service

已解决!最终解决方案见下文

问题: 我正在尝试将数据绑定和 MVVM 用于 android 应用程序,但问题在于模型是由与应用程序的 MVVM 部分分开的服务更新的。 如果我通过 viewmodel 更新模型它工作正常,但我似乎无法找到一种干净的方法来更改模型以冒泡到 viewmodel,然后在服务更新模型时到视图.

应用程序: 该应用程序通过蓝牙连接到外部设备,然后保持串行连接,传感器读数和设置以接近实时的方式从设备连续流式传输到应用程序。命令也可以通过此连接发送到设备。 该模型充当设备的内存表示。应用程序中的不同屏幕向用户展示模型的不同部分,可能允许也可能不允许他们调整某些值(设置)。

代码:(我无法显示我的确切代码,但这是一个简化版本)

型号:

public class DeviceModel extends BaseObservable {

private int mode;

@Bindable
public int getMode(){
    return mode;
}

public void setMode(int mode) {
    this.mode = mode;
    notifyPropertyChanged(BR.mode);
}
}

视图模型:

public class BasicViewViewModel extends BaseObservable {
private final Context mContext;
private ObservableField<DeviceModel> modelFields;

public BasicViewViewModel(Context context){
    mContext = context.getApplicationContext();
    ApplicationBase app = ApplicationBase.getInstance();
    modelFields = new ObservableField<>(app.dModel);
}

    @Bindable
public String getMode(){
    return modelFields.get().Mode;
}
}

片段:

public class BasicViewFragment extends Fragment {
private FragmentBasicViewBinding mBinding;
private BasicViewViewModel mViewModel;

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState){
    mViewModel = new BasicViewViewModel(getContext());
    mBinding = DataBindingUtil.inflate(
            inflater, R.layout.fragment_basic_view, container, false);
    View view = mBinding.getRoot();
    mBinding.setDevice(mViewModel);
    return view;
}
}

布局:

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<data>
    <variable name="device" type="com.example.android.bluetoothcomms.BasicViewViewModel"/>
</data>
<RelativeLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent">

<TextView
    android:text="@{device.mode}"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:id="@+id/tvModeVal" />

</RelativeLayout>
</layout>

自定义应用代码:

public class ApplicationBase extends Application {

private static ApplicationBase instance;
public BluetoothCommsService btComms;
public DeviceModel dModel;


@Override
public void onCreate(){
    super.onCreate();
    instance = this;
    dModel = new DeviceModel();
    btComms = new BluetoothCommsService();

}

public static ApplicationBase getInstance(){
    return instance;
}
}

解决方案 最后我听从了@exkoria 的建议并使用 EventBus 创建并发送了一个自定义事件:

public class DeviceModelUpdateEvent {

public final String fieldName;
public final String newValue;

public DeviceModelUpdateEvent(String field, String value){
    fieldName = field;
    newValue = value;
}
}

我在我的视图模型中放置了一个处理程序来触发视图中的数据绑定更新:

@Subscribe
public void onMessageEvent(DeviceModelUpdateEvent event){
    switch(event.fieldName){
        case "yieldLevel":
            notifyPropertyChanged(BR.yieldLevel);
            break;
        case "mode":
            notifyPropertyChanged(BR.mode);
            break;
        case "deviceType":
            notifyPropertyChanged(BR.deviceType);
            break;
        case "firmwareVersion":
            notifyPropertyChanged(BR.firmwareVersion);
    }
}

您不能只向您的模型添加一个侦听器,以便您的视图模型可以侦听模型中的更改并在发生更改时更新视图吗?或者它可能是事件总线的一个很好的用法,例如这个:https://github.com/greenrobot/EventBus