В настоящее время я работаю над приложением android с API Google Firebase. Мне нужно получать сообщения из моей иерархии базы данных в реальном времени, чтобы получить значение из базы данных в реальном времени, мне нужно создать ValueEventListener и получить результат. Проблема здесь в том, что я использую метод stati c для получения сообщений из базы данных, я пытался переместить задание обратного вызова в метод, который использует метод stati c с com.google.android.gms.tasks.Task
и com.google.android.gms.tasks.TaskCompletionSource
, но в во второй раз, когда вы вызываете метод stati c после его окончания (после оператора return), значения переменных метода stati c изменяются на значения первого вызова.
Вот код для получения сообщений из базы данных :
public static Task<List<Task<Message>>> loadMessages() {
List<Task<Message>> messagesTasks = new ArrayList<>();
TaskCompletionSource<List<Task<Message>>> messagesTCS = new TaskCompletionSource<>();
DatabaseReference userMessagesRef = FirebaseDatabase.getInstance().getReference("users").child(FirebaseAuth.getInstance().getUid()).child("messageIDS");
DatabaseReference messagesRef = FirebaseDatabase.getInstance().getReference("messages");
System.out.println("start");
System.out.println(messagesTCS);
userMessagesRef.addValueEventListener(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot snapshot : dataSnapshot.getChildren()) {
TaskCompletionSource<Message> messageTCS = new TaskCompletionSource<>();
String messageID = (String) snapshot.getValue();
messagesRef.child(messageID).addValueEventListener(new ValueEventListener() {
@Override
public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
messageTCS.setResult(dataSnapshot.getValue(Message.class));
}
@Override
public void onCancelled(@NonNull DatabaseError databaseError) {
Log.w(TAG, "Failed to read value.", databaseError.toException());
messageTCS.setResult(null);
}
});
Task messageTask = messageTCS.getTask();
messagesTasks.add(messageTask);
}
System.out.println("end");
System.out.println(messagesTCS);
messagesTCS.setResult(messagesTasks);
}
@Override
public void onCancelled(DatabaseError error) {
Log.w(TAG, "Failed to read value.", error.toException());
messagesTCS.setResult(null);
}
});
return messagesTCS.getTask();
}
Вот код, который ожидает результатов задач:
Message.loadMessages().addOnCompleteListener(new OnCompleteListener<List<Task<Message>>>() {
@Override
public void onComplete(@NonNull Task<List<Task<Message>>> messagesTasksTask) {
for(Task<Message> messageTask : messagesTasksTask.getResult())
{
messageTask.addOnCompleteListener(new OnCompleteListener<Message>() {
@Override
public void onComplete(@NonNull Task<Message> messageTask) {
adapter.addMessage(messageTask.getResult());
}
});
}
}
});
Каков наилучший способ предотвратить такое поведение? Есть ли лучший способ сделать то, что мне нужно, не разрушая иерархию классов?
Редактировать: После второго раза я вызываю loadMessages
, когда приложение печатает «start» messagesTCS значение будет новым, но когда оно печатает «end» messagesTCS будет первым вызовом loadMessages
(я заметил, что это происходит, потому что я больше не в этом методе, но я не уверен, что это лучший способ исправить это).