Как LiveData в ViewModel может наблюдать Livedata в репозитории с помощью трансформаций?

Я использую AsyncTask в моем хранилище, которое используется для установки LiveData в хранилище. Как мне наблюдать эти LiveData из моей ViewModel, используя Transformations?

2 ответа

Вы можете игнорировать мой другой ответ. Решение использует MediatorLiveData<> в вашей модели представления. Вы добавляете LiveData из хранилища в качестве источника данных к MediatorLiveData <> и вызываете setValue или postValue (зависит от того, находится ли он в протекторе пользовательского интерфейса или нет) в обратном вызове onChanged наблюдателя.

Вот так

    currentTransaction.addSource(application.getFinanceRepository().getTransaction(id),
            new Observer<Transaction>() {
        @Override
        public void onChanged(@Nullable Transaction transaction) {
            //Updates the MediatorLiveData<> that you activity is observing
            currentTransaction.setValue(transaction);
        }
    });

Так что сегодня я пробовал именно это и не мог заставить его работать. Я пробовал оба

Transformations.switchMap(application.getFinanceRepository().getTransaction(id),
            new Function<Transaction, LiveData<Transaction>>() {
                @Override
                public LiveData<Transaction> apply(Transaction input) {
                    Log.d(TAG, "apply: VIewModel Transaction changed: " + input.toString());
                    //Set the inital transaction to track changes
                    initialTransaction = input;

                    //Update the transaction observed by the activity/fragment
                    currentTransaction.setValue(input);
                    return currentTransaction;
                }
            });

а также

Transformations.map(loading,
            new Function<Transaction, Object>() {
                @Override
                public Object apply(Transaction input) {
                    //Set the inital transaction to track changes
                    initialTransaction = new Transaction(input);

                    //Update the transaction observed by the activity/fragment
                    currentTransaction.setValue(input);
                    return null;
                }
            });

где currentTransaction - MutableLiveData, а initalTransaction - просто объект Transaction. application.getFinanceRepository().getTransaction(id) возвращает LiveData

Это скомпилировано нормально, но не работает должным образом. apply() никогда не вызывался, и я остался с нулевой транзакцией. Я не мог понять, как заставить это загрузить кое-что.

Чтобы обойти это, я вернул application.getFinanceRepository (). GetTransaction (id) обратно во фрагмент / действие. Наблюдатель для этого затем вызовет метод в viewModel, чтобы вернуть транзакцию обратно в модель представления.

public void transactionLoaded(Transaction transaction) {
    initialTransaction = new Transaction(transaction);
    currentTransaction.setValue(transaction);
}

Затем я также установил активность, чтобы также наблюдать currentTransaction MutableLiveData

Еще несколько фрагментов, чтобы, надеюсь, прояснить, что я сделал.

Fragment.java onActivityCreated ()

    viewModel.loadTransaction(id).observe(this, new Observer<Transaction>() {
        @Override
        public void onChanged(@Nullable Transaction transaction) {
            viewModel.transactionLoaded(transaction);
        }
    });

    viewModel.getTransaction().observe(this, new Observer<Transaction>() {
        @Override
        public void onChanged(@Nullable Transaction trans) {
            //When new LiveData arrives update the transaction and then the views
            Log.d(TAG, "onChanged: transaction changed: " + trans.toString());
            transaction = trans;
            updateViews();
        }
    });

TransactionViewModel.java соответствующие части

private Transaction initialTransaction;
private final MutableLiveData<Transaction> currentTransaction = new MutableLiveData<>();

public LiveData<Transaction> loadTransaction(int id) {
    return application.getFinanceRepository().getTransaction(id);
}


public void transactionLoaded(Transaction transaction) {
    initialTransaction = new Transaction(transaction);
    currentTransaction.setValue(transaction);
}

Это не идеально, потому что это не будет работать, если фрагмент / деятельность не участвует, но он работает.