![](/img/trans.png)
[英]Android MVVM architecture and observing changes on data from an API
[英]Observing Multiple LiveData and MVVM Structure Android Java
我會盡量使這個問題籠統地說。
簡而言之,我使用的是 FireStore Firebase,我想做的是我有兩個存儲庫(TransactionsRepository 和 VaultAccountRepository),每個存儲庫都有一些查詢要添加(事務或 VaultAccount 對象)、編輯、刪除等......
我創建了第三個存儲庫(OperationRepository),我想(例如)在其中獲取所有交易並讓默認帳戶對它們進行操作(例如將所有交易金額與帳戶初始值相加等等)並得到它操作作為活動數據在視圖中觀察它。
這里的想法是我不知道如何觀察交易和默認帳戶來更新返回的操作並因此更新 UI
我已經閱讀了有關Transformation.map
和Transformation.switchMap
的信息,但我根本無法理解它們,大多數示例都在 Kotlin 中,我什至不確定這是我正在尋找的。 並且不確定這個結構是否正確,因為我是 MVVM 的新手。
我將包含一些代碼來展示我試圖做的事情,以防我上面的解釋不夠清楚。
public class VaultRepository {
...
private final MutableLiveData<VaultAccount> defaultVaultLiveData;
...
public MutableLiveData<VaultAccount> getDefaultVault() {
fireStore.collection("users").document(firebaseUser.getUid()).collection("vaults")
.whereEqualTo("defaultAccount", true)
.addSnapshotListener((value, error) -> {
VaultAccount vaultAccount = new VaultAccount();
if (value != null) {
for (QueryDocumentSnapshot doc : value) {
if (doc != null) {
vaultAccount = doc.toObject(VaultAccount.class);
}
}
defaultVaultLiveData.postValue(vaultAccount);
}
});
return defaultVaultLiveData;
}
}
public class TransactionRepository {
...
private final MutableLiveData<List<Transaction>> allTransactionsLiveData;
...
public MutableLiveData<List<Transaction>> getAllTransactions() {
fireStore.collection("users").document(firebaseUser.getUid())
.collection("transactions")
.orderBy("transactionDate")
.addSnapshotListener((value, error) -> {
List<Transaction> transactionList = new ArrayList<>();
if (value != null) {
for (QueryDocumentSnapshot doc : value) {
if (doc != null) {
Transaction transaction = doc.toObject(Transaction.class);
transactionList.add(transaction);
}
}
allTransactionsLiveData.postValue(transactionList);
}
});
return allTransactionsLiveData;
}
}
舊的操作存儲庫
public class OperationRepository {
private final Application mApplication;
private TransactionRepository transactionRepository;
private VaultRepository vaultRepository;
private MutableLiveData<String> stringMutableLiveData;
public OperationRepository(Application mApplication) {
this.mApplication = mApplication;
transactionRepository = new TransactionRepository(mApplication);
vaultRepository = new VaultRepository(mApplication);
stringMutableLiveData = new MutableLiveData<>();
}
public MutableLiveData<String> getFinalAmount() {
//TODO get all the transactions and get there amount and observe it
// get the account initial amount and observe it
//add all the values and present it in a String LiveData to be shown in the view
double result = 0;
String finalResult = String.valueOf(result);
stringMutableLiveData.postValue(finalResult);
return stringMutableLiveData;
}
}
更新:我將我的 OperationRepository 更改為 OperationVeiwModel 並嘗試使用Transformation.switchMap
。
public class OperationViewModel extends AndroidViewModel {
private final TransactionRepository transactionRepository;
private final VaultRepository vaultRepository;
private MutableLiveData<List<Transaction>> transactionListLiveData;
private MutableLiveData<VaultAccount> vaultAccountLiveData;
private LiveData<Double> transactionTotal;
private LiveData<Double> accountAmount;
LiveData<String> totalAmount;
public OperationViewModel(@NonNull Application application) {
super(application);
transactionRepository = new TransactionRepository(application);
vaultRepository = new VaultRepository(application);
transactionListLiveData = new MutableLiveData<>();
vaultAccountLiveData = new MutableLiveData<>();
}
double result = 0;
public LiveData<String> getFinalAmount() {
transactionListLiveData = transactionRepository.getAllTransactions();
vaultAccountLiveData = vaultRepository.getDefaultVault();
transformations();
final MutableLiveData<Double> resultLive = new MutableLiveData<>();
try {
result = transactionTotal.getValue() + accountAmount.getValue();
} catch (NullPointerException e) {
Toast.makeText(getApplication(), e.getMessage(), Toast.LENGTH_LONG).show();
e.printStackTrace();
}
resultLive.postValue(result);
totalAmount = Transformations.switchMap(resultLive, data -> {
final MutableLiveData<String> result = new MutableLiveData<>();
String total = String.valueOf(data);
result.postValue(total);
return result;
});
return totalAmount;
}
private void transformations() {
transactionTotal = Transformations.switchMap(transactionListLiveData, transactionsList -> {
final MutableLiveData<Double> result = new MutableLiveData<>();
double amount = 0;
for (int i = 0; i < transactionsList.size(); i++) {
double itemAmount = Double.parseDouble(transactionsList.get(i).getTransactionAmount());
amount += itemAmount;
}
result.postValue(amount);
return result;
});
accountAmount = Transformations.switchMap(vaultAccountLiveData, vault -> {
final MutableLiveData<Double> result = new MutableLiveData<>();
result.postValue(Double.valueOf(vault.getInitAmount()));
return result;
});
}
}
代碼沒有按我的預期工作,這表明我不知道自己在做什么。
不過,我嘗試測試此代碼並發現以下內容:
1-當我第一次調用 getFinalAmount 並在視圖中觀察它時,兩個存儲庫返回 null 但如果我對觀察到的 LiveData 進行更改,它們將返回我想要獲取的實時數據。
2-轉換方法中的 switchMap 根本不起作用。
我在另一個問題中找到了我的問題的解決方案(因此我的問題將被視為重復)。
解決方案(我的問題)可以在這里找到。 我需要的是一個MediatorLiveData
來將我的兩個實時數據組合成一個實時數據並觀察它。
public class CombinedLiveData2<A, B> extends MediatorLiveData<Pair<A, B>> {
private A a;
private B b;
public CombinedLiveData2(LiveData<A> ld1, LiveData<B> ld2) {
setValue(Pair.create(a, b));
addSource(ld1, (a) -> {
if(a != null) {
this.a = a;
}
setValue(Pair.create(a, b));
});
addSource(ld2, (b) -> {
if(b != null) {
this.b = b;
}
setValue(Pair.create(a, b));
});
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.