与 DataBinding 一起使用时,LiveData 不会通知 UI 有关更改

LiveData doesn't notify UI about changes when used with DataBinding

我想更改 UI,因为 LiveData 在与 DataBinding 一起使用时会更改。但随着 LiveData 的变化,它并未反映 UI.

的变化

MainViewModel.java

public class MainViewModel extends AndroidViewModel {
    /**
     * Boolean variable to see whether user is ClockedIn or ClockedOut
     */
    public MutableLiveData<Boolean> isClockedIn;

    public MainViewModel(Application application) {
        super(application);
        isClockedIn = new MutableLiveData<>();
        //...
        calculateClockedInOrNot(PreferencesManager.getString(mContext,PreferencesManager.CLOCK_STATUS_KEY));
    }

    /**
     * An utility function to calculate whether user is clocked in or clocked out,
     * this function is also called within this ViewModel after an api hit
     *
     * if string == "CLOCKED_OUT" or string == "mobileEventType.CLOCK_OUT" => user is clocked out
     * else user is clocked in
     */
    private void calculateClockedInOrNot(String string) {
        if (string.equals("CLOCKED_OUT") || string.equals("mobileEventType.CLOCK_OUT")) {
            //user is clocked out
            isClockedIn.setValue(false);
        } else {
            //user is clocked in
            isClockedIn.setValue(true);
        }
    }
    //getter function
    public MutableLiveData<Boolean> isClockedIn() {
        return isClockedIn;
    }
    //other function left for brevity
}

MainActivity.java

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    // Obtain the ViewModel component.
    mainViewModel = ViewModelProviders.of(this).get(MainViewModel.class);
    // Inflate view and obtain an instance of the binding class.
    ActivityMainBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_main);
    // Assign the component to a property in the binding class.
    binding.setData(mainViewModel);
}

activity_main.xml

<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:bind="http://schemas.android.com/apk/res-auto"

xmlns:tools="http://schemas.android.com/tools">

<data>

    <variable
        name="data"
        type="com.app.bidunity.viewmodel.MainViewModel" />
</data>

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

        <ImageView
            android:id="@+id/imageView"
            android:layout_width="wrap_content"
            android:layout_height="@dimen/img_hight_location"
            android:adjustViewBounds="true"
            android:src="@{data.clockedIn ? @drawable/ic_location_on : @drawable/ic_location_off}"/>
        <!--Other view left for brevity-->
 </LinearLayout>
</layout>

build.gradle

apply plugin: 'com.android.application'

android {
    compileSdkVersion 28
    defaultConfig {
        applicationId "com.app.bidunity"
        minSdkVersion 17
        targetSdkVersion 28
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
        vectorDrawables.useSupportLibrary = true
    }
buildTypes {
    release {
        minifyEnabled false
        proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
    }
}
dataBinding {
    enabled = true
}
compileOptions {
    sourceCompatibility = '1.8'
    targetCompatibility = '1.8'
}


}

dependencies {
def arch_version = "2.0.0-rc01"

implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'androidx.appcompat:appcompat:1.0.0'
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
//material library
implementation 'com.google.android.material:material:1.0.0'
// ViewModel and LiveData
implementation "androidx.lifecycle:lifecycle-extensions:$arch_version"

testImplementation 'junit:junit:4.12'
androidTestImplementation 'androidx.test:runner:1.1.0-alpha4'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.0-alpha4'
}

我正在使用 Android studio 3.3 Canary 11 以及 gradle 4.10.1onclick 与数据绑定在 viewmodel 中工作正常,但即使在更改 isClockedIn 之后 ImageView 也没有改变它的可绘制性。我已经尝试了一切,我什至调试以查看 isClockedIn 是否在 运行 的中间发生变化,是的,它的值正在发生变化

你需要让你的 isClockedIn 变量 Observable Field,

所以从

替换它
public boolean isClockedIn = false;

public ObservableBoolean isClockedIn = new ObservableBoolean();

注意:还要确保 xml 与 ViewModel

中的变量名称相同

参考here

编辑:

如果你不想做ObservableField,那么它需要做一些其他的改变。

尽管有 ObservableField,您仍需要使您的可观察对象扩展 BaseObservable 并在您的 livedata 您需要在布尔值更改后调用 notifyPropertyChanged(BR.isClockedIn);


如果你想使用 LiveData 作为观察者,首先是为你的绑定提供一个生命周期

// Specify the current activity as the lifecycle owner (in your activity/fragment).
binding.setLifecycleOwner(this);

在您的 ViewModel 中,使用 LiveData 对象观察变化并对其应用 Transformation

MutableLiveData<Boolean> dataToBeObserve = new MutableLiveData<>();
LiveData booleanDataChange = Transformations.map(dataToBeObserve, dataToBeObserve-> dataToBeObserve.value);

现在,使用此 booleanDataChange 到 xml 并更改您的 MutableLiveData 值以观察数据更改事件。

注意:您可以对更改事件使用相同的 LiveData,只需要将定义拆分为构造函数调用即可。