Математические операции с живыми данными

#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));
        }
    });
    }
});