У меня есть одноэлементный класс, содержащий мои предпочтения, и я пытаюсь привязать поле, которое изменит формат при изменении предпочтения.
Это своего рода работа (поле открыто), но оно только обновляет поле при изменении текста, а не при изменении предпочтения.
Я пытался вызвать notifyPropertyChanged(BR.useDecimalTime);
, пытался наблюдать событие SingleLiveData
(которое вызывается и вызывает executePendingBindings()
, но не не обновлять формат).
Некоторые соответствующие фрагменты кода:
PreferenceRepository. java
public class PreferenceRepository extends BaseObservable implements SharedPreferences.OnSharedPreferenceChangeListener {
public static final String DECIMAL_TIME = "pref_decimal_time";
private static boolean useDecimalTime;
private SingleLiveEvent<Object> prefsUpdated = new SingleLiveEvent<>();
@Contract(pure = true)
@Bindable
public static boolean isUseDecimalTime() {
return useDecimalTime;
}
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, @NotNull String key) {
switch (key) {
case DECIMAL_TIME:
useDecimalTime = sharedPreferences.getBoolean(key, false);
notifyPropertyChanged(BR.useDecimalTime);
break;
default:
Log.e(TAG, "onSharedPreferenceChanged: Unknown key ["+key+"]");
}
prefsUpdated.call();
}
Фрагмент. xml
<data>
<import type="java.util.Map"/>
<import type="android.view.View" />
<variable
name="viewmodel"
type="com.example.HomeViewModel" />
<variable
name="prefs"
type="com.example.prefs.PreferenceRepository" />
</data>
<com.example.ui.view.timetextview.TimeView
android:id="@+id/shiftHoursView"
style="@style/TextAppearance.MyTheme.Mono"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
minutes="@{viewmodel.shiftMinutes}"
mode="@{prefs.isUseDecimalTime}"
app:layout_constraintBaseline_toBaselineOf="@id/textView11"
app:layout_constraintStart_toStartOf="@id/guideline_33"
tools:text="0:00" />
и соответствующий BindingAdapters. java метод для полноты:
@Contract("null, _, _ -> fail")
@BindingAdapter(value = {"minutes", "mode"}, requireAll = false)
public static void setTimeMinutes(View view, Integer minutes, Boolean decimal) {
if(!(view instanceof TimeView)) {
throw new UnsupportedOperationException("Can only set minutes on a TimeView");
}
if(view.getVisibility() != View.VISIBLE) return;
if(minutes == null) {
minutes = 0;
Log.e(TAG, "setTimeMinutes: null minutes");
}
if(decimal == null) {
((TimeView) view).setTime(minutes);
} else {
((TimeView) view).setTime(minutes, decimal);
}
}
TimeView
- это пользовательское представление, которое расширяет TextView
, если это имеет значение.
РЕДАКТИРОВАТЬ:
При вызове binding.invalidateAll()
все обновляется немедленно, но мне остается только задаться вопросом, является ли это правильным способом сделать это или если есть лучший способ.