#android-livedata
#android-livedata
Вопрос:
У меня есть две живые данные. Мне нужно произвести вычитание для них, но как это сделать с двумя живыми данными?
Я создал что-то вроде этого, но это неправильный способ, потому что он не всегда обновляет результат, когда мне это нужно.
totalFragmentViewModel.getTotalExpenseValue().observe(getViewLifecycleOwner(), new Observer<Double>() {
@Override
public void onChanged(Double aDouble) {
expenseTextView.setText(String.valueOf(aDouble));
mExpense = aDouble;
balanceTextView.setText(String.valueOf(mIncome - mExpense));
}
});
totalFragmentViewModel.getTotalIncomeValue().observe(getViewLifecycleOwner(), new Observer<Double>() {
@Override
public void onChanged(Double aDouble) {
incomeTextView.setText(String.valueOf(aDouble));
mIncome = aDouble;
balanceTextView.setText(String.valueOf(mIncome - mExpense));
}
});
Ответ №1:
Вы можете использовать MediatorLiveData
для агрегирования нескольких источников. В вашем случае это будет агрегирование событий изменения (данные будут игнорироваться), например, ваша модель представления может быть реализована следующим образом:
class MyViewModel extends ViewModel {
private MutableLiveData<Double> expense = new MutableLiveData<>();
private MutableLiveData<Double> income = new MutableLiveData<>();
private MediatorLiveData<Double> balance = new MediatorLiveData<>();
public MyViewModel() {
// observe changes of expense and income
balance.addSource(expense, this::onChanged);
balance.addSource(income, this::onChanged);
}
@AnyThread
public void updateExpense(Double value) {
expense.postValue(value);
}
@AnyThread
public void updateIncome(Double value) {
income.postValue(value);
}
// expose balance as LiveData if you want only observe it
public LiveData<Double> getBalance() {
return balance;
}
// argument is ignored because we don't know expense it or it is income
private void onChanged(@SuppressWarnings("unused") Double ignored) {
Double in = income.getValue(), ex = expense.getValue();
// correct value or throw exception if appropriate
if (in == null)
in = 0.0;
if (ex == null)
ex = 0.0;
// observer works on the main thread, we can use setValue() method
// => avoid heavy calculations
balance.setValue(in - ex);
}
}
Ответ №2:
Попробуйте это:
totalFragmentViewModel.getTotalExpenseValue().observe(getViewLifecycleOwner(), new Observer<Double>() {
@Override
public void onChanged(Double expense) {
expenseTextView.setText(String.valueOf(expense));
mExpense = expense;
totalFragmentViewModel.getTotalIncomeValue().observe(getViewLifecycleOwner(), new Observer<Double>() {
@Override
public void onChanged(Double income) {
incomeTextView.setText(String.valueOf(income));
mIncome = income;
balanceTextView.setText(String.valueOf(mIncome - mExpense));
}
});
}
});