Проблема вычисления в классе помощника - возвращение выполняется до расчета - PullRequest
0 голосов
/ 31 марта 2019

Моя текущая проблема заключается в том, что я хочу создать класс Helper, который вычисляет мои затраты (хранящиеся в базе данных), чтобы все было организовано лучше (потому что мне нужно это вычисление в двух моих видах деятельности).

Прямо сейчас код вычисления (который работает нормально) просто написан внутри двух действий (что делает все довольно уродливым).

Итак: я создал класс "CostIntervalHelper".

Я положил туда свой код и изменил несколько вещей, но сейчас я столкнулся с большой проблемой. Чтобы объяснить это лучше, сначала приведем код метода расчета:

 public BigDecimal calculateMonthlyCosts(SubViewModel subViewModel, Context context){
    //set this two times just for debugging reasons to see if the calculation actually works
    cMonthly = new BigDecimal(0);

    subViewModel.getAllMonthlyCosts().observe((LifecycleOwner) context, new Observer<BigDecimal>() {
        @Override
        public void onChanged(@Nullable BigDecimal bigDecimal) {
            cMonthly = new BigDecimal(0);
            if (bigDecimal != null) {
                cMonthly = cMonthly.add(bigDecimal);
            }
        }
    });

    subViewModel.getAllBiannuallyCosts().observe((LifecycleOwner) context, new Observer<BigDecimal>() {
        @Override
        public void onChanged(@Nullable BigDecimal bigDecimal) {
            cBiannually = new BigDecimal(0);
            if (bigDecimal != null) {
                cBiannually = cBiannually.add(bigDecimal.divide(new BigDecimal(6), 2));
            }
        }
    });

    subViewModel.getAllYearlyCosts().observe((LifecycleOwner) context, new Observer<BigDecimal>() {
        @Override
        public void onChanged(@Nullable BigDecimal bigDecimal) {
            cYearly = new BigDecimal(0);
            if (bigDecimal != null) {
                cYearly = cYearly.add(bigDecimal.divide(new BigDecimal(12), 2));
                cMonthly = cMonthly.add(cBiannually).add(cYearly);
            }
        }
    });

    //return is hit before the calculation so it only returns "0"
    return cMonthly;
}

Теперь перейдем к проблеме (уже добавили несколько комментариев в код):

Всякий раз, когда я вызываю метод, сначала вызывается возврат cMonthly. В режиме отладки я проверил и могу сказать: ПОСЛЕ ТОГО, КАК оператор возврата был нажат, вычисление выполнено (в правильном направлении).

Теперь мне нужна идея или пример, как я могу сделать свой код ПЕРВЫМ (в правильном порядке), чтобы все методы subViewModel.getAll(Monthly/Biannually/Yearly)Costs().[...] и AFTERWARDS выполняли оператор return.

Я знаю, что это немного сложно, потому что я использую LiveData / ViewModel, но, возможно, у кого-то есть идея! Было бы здорово! Спасибо вперед!

1 Ответ

1 голос
/ 31 марта 2019
public BigDecimal calculateMonthlyCosts(SubViewModel subViewModel...) {

Если вы используете LiveData, то ваши вычисления не должны выполняться немедленно в виде синхронной функции.

Вы не хотите возвращать BigDecimal, вы хотитесоздайте LiveData, основанную на цепочке между вашими другими LiveData, которая будет обновлять BigDecimal при изменении любого из LiveData.

Для этого вы должны создать одну MediatorLiveData и наблюдать, что LiveData получит последнее значениеBigDecimal всякий раз, когда изменяется любой из его «компонентов».

public LiveData<BigDecimal> calculateMonthlyCosts(SubViewModel subViewModel) {
    MediatorLiveData<BigDecimal> mediator = new MediatorLiveData<>() {
        private BigDecimal cMonthly = new BigDecimal(0);
        private BigDecimal cBiannually = new BigDecimal(0);
        private BigDecimal cYearly = new BigDecimal(0);

        {
            addSource(subViewModel.getAllMonthlyCosts(), new Observer<BigDecimal>() {
                @Override
                public void onChanged(@Nullable BigDecimal bigDecimal) {
                    if (bigDecimal != null) {
                        cMonthly = cMonthly.add(bigDecimal);
                        setValue(cMonthly);
                    }
                }
            });

            addSource(subViewModel.getAllBiannuallyCosts(), new Observer<BigDecimal>() {
                @Override
                public void onChanged(@Nullable BigDecimal bigDecimal) {
                    if (bigDecimal != null) {
                        cBiannually = cBiannually.add(bigDecimal.divide(new BigDecimal(6), 2));
                        setValue(cMonthly); // TODO: ???
                    }
                }
            });

            addSource(subViewModel.getAllYearlyCosts(), new Observer<BigDecimal>() {
                @Override
                public void onChanged(@Nullable BigDecimal bigDecimal) {
                    if (bigDecimal != null) {
                        cYearly = cYearly.add(bigDecimal.divide(new BigDecimal(12), 2));
                        cMonthly = cMonthly.add(cBiannually).add(cYearly);
                        setValue(cMonthly);
                    }
                }
            });
         }
    };

    return mediator;
}

Обратите внимание, что я не на 100% уверен в вашей бизнес-логике, и, возможно, мне придется пойти по пути «использования кортежей для объединения нескольких LiveData»как указано здесь или здесь .

Вы также можете обратиться к этому видео .

...