问题
I am currently trying to run a query on my firebase DB, I can see the values that I want in my logs but my method always returns an empty arraylist.
Kindly find my code below:
public static ArrayList<Transaction> getUserTransactions(String userId){
Query userTransactionQuery = mDatabaseReference
.child("transactions")
.orderByChild("userId")
.equalTo(userId);
final ArrayList<Transaction> transactionsByUser = new ArrayList<>();
userTransactionQuery.addValueEventListener(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot transactionSnapshot: dataSnapshot.getChildren()) {
// TODO: handle the post
Transaction t = transactionSnapshot.getValue(Transaction.class);
transactionsByUser.add(t);
Log.w(TAG, t.toString());
}
Log.i(TAG, "Collected User Transactions");
}
@Override
public void onCancelled(DatabaseError databaseError) {
// Getting Transaction failed, log a message
Log.w(TAG, "loadTransactions:onCancelled", databaseError.toException());
// ...
}
});
return transactionsByUser;
}
My POJO:
public class Transaction {
private String id;
private String userId;
private String categoryId;
private TransactionType transactionType;
private String creationDate;
private long amount;
private String description;
/**
* No args constructor
*/
public Transaction () {}
/**
* Constructor for the Transaction object
* @param userId id of the user who made the transaction
* @param categoryId ID of the category the transaction belongs under
* @param amount amount spent/received
* @param transactionType income/expense
*/
public Transaction(String userId, String categoryId, TransactionType transactionType, long amount, String description) {
this.userId = userId;
this.categoryId = categoryId;
this.transactionType = transactionType;
this.amount = amount;
this.description = description;
//Date last changed will always be set to ServerValue.TIMESTAMP
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
String currentDateTime = dateFormat.format(new Date()); // Find todays date
this.creationDate = currentDateTime;
}
/**
* Transaction Id Getter
* @return transaction Id
*/
public String getId() {
return id;
}
/**
* Transaction Id Setter
* @param id Id to assign to the user
*/
public void setId(String id) {
this.id = id;
}
/**
* Category Id getter
* @return category Id under which the transaction belongs
*/
public String getCategoryId() {
return categoryId;
}
/**
* Category Id setter
* @param categoryId category Id under which the transaction belongs
*/
public void setCategoryId(String categoryId) {
this.categoryId = categoryId;
}
/**
* Transaction type getter
* @return type of the transaction whether its an income or an expense
*/
public TransactionType getTransactionType() {
return transactionType;
}
/**
* Transaction type setter
* @param transactionType type of the transaction to set
*/
public void setTransactionType(TransactionType transactionType) {
this.transactionType = transactionType;
}
/**
* Transaction creation date getter
* @return creation date of the transaction
*/
public String getCreationDate() {
return creationDate;
}
/**
* Transaction creation date setter
* @param creationDate creation date to set to the transaction
*/
public void setCreationDate(String creationDate) {
this.creationDate = creationDate;
}
/**
* Transaction amount getter
* @return amount set
*/
public long getAmount() {
return amount;
}
/**
* Transaction amount setter
* @param amount amount to set
*/
public void setAmount(long amount) {
this.amount = amount;
}
/**
* User Id getter
* @return user id corresponding to the transaction
*/
public String getUserId() {
return userId;
}
/**
* User Id setter
* @param userId user id to set to the transaction
*/
public void setUserId(String userId) {
this.userId = userId;
}
/**
* Description getter
* @return Description corresponding to the transaction
*/
public String getDescription() {
return description;
}
/**
* Description setter
* @param description Description to set to the transaction
*/
public void setDescription(String description) {
this.description = description;
}
/**
* Transaction object string representation
* @return object represented in a string
*/
@Override
public String toString() {
return "Transaction{" +
"id='" + id + '\'' +
", userId='" + userId + '\'' +
", categoryId='" + categoryId + '\'' +
", transactionType=" + transactionType +
", creationDate='" + creationDate + '\'' +
", amount=" + amount +
'}';
}
}
My JSON tree looks like:
{
transactions:
{
transactionId {
pojo
}
}
}
In brief: what I'm trying to do is get all the transactions made by a user using his user ID, Im trying to store the result in an array list but the array list always returns empty;
回答1:
So this is just an attempt to answer your question:
public static void getUserTransactions(String userId, final ArrayList<Transaction> transactionsByUser){
Query userTransactionQuery = mDatabaseReference
.child("transactions")
.orderByChild("userId")
.equalTo(userId);
userTransactionQuery.addValueEventListener(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot transactionSnapshot: dataSnapshot.getChildren()) {
// TODO: handle the post
Transaction t = transactionSnapshot.getValue(Transaction.class);
transactionsByUser.add(t);
Log.w(TAG, t.toString());
}
Log.i(TAG, "Collected User Transactions");
}
@Override
public void onCancelled(DatabaseError databaseError) {
// Getting Transaction failed, log a message
Log.w(TAG, "loadTransactions:onCancelled", databaseError.toException());
// ...
}
});
}
Usage
ArrayList<Transaction> transactions = new ArrayList<>();
getUserTransactions("{userId}", transactions);
//check after method call while debugging if transactions is empty
If this does not work you going to have to use this event implementation where the ArrayList is being used. Be aware that Firebase queries are asynchronous.
回答2:
Use LiveData
to solve synchronization problem in asynchronous
operation.
private static MutableLiveData<ArrayList<Transaction>> mutableTransactionsByUser = new MutableLiveData<>();
public static MutableLiveData<ArrayList<Transaction>> getUserTransactions(String userId){
Query userTransactionQuery = mDatabaseReference
.child("transactions")
.orderByChild("userId")
.equalTo(userId);
final ArrayList<Transaction> transactionsByUser = new ArrayList<>();
userTransactionQuery.addValueEventListener(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot transactionSnapshot: dataSnapshot.getChildren()) {
// TODO: handle the post
Transaction t = transactionSnapshot.getValue(Transaction.class);
transactionsByUser.add(t);
Log.w(TAG, t.toString());
}
//Post here
mutableTransactionsByUser.postValue(transactionsByUser);
Log.i(TAG, "Collected User Transactions");
}
@Override
public void onCancelled(DatabaseError databaseError) {
// Getting Transaction failed, log a message
Log.w(TAG, "loadTransactions:onCancelled", databaseError.toException());
// ...
}
});
return mutableTransactionsByUser;
}
And then from your Activity/Fragment
observe like below:
getUserTransactions(userId).observe(this, new Observer<ArrayList<Transaction>>() {
@Override
public void onChanged(ArrayList<Transaction> transactions) {
// Do your operation here
}
});
来源:https://stackoverflow.com/questions/43048957/empty-arraylist-firebase-data-retrieval