Ожидание потоков в android java
Работаю с firebase, появилась задача ожидать завершения потоков, но реализация хромает.
У меня структура такая : обращаюсь по пути N получаю массив клиентов (id), этот массив клиентов так же содержит массив информации, который хранится по пути M, обращаюсь M, получаю информацию, записываю.
Проблема в том, что получение информации по пути M происходит асинхронно и мне нужно дождаться ответа. Я такое реализовал в ios с помощью dispatchgroup, на andoroid попытался использовать CountDownLatch, но либо я что-то не так делаю, либо он сюда не подходит. Моя попытка :
void getClients(){
DatabaseReference ref = dataFirebase.scheduleReference.child(dataFirebase.currentId).child("list");
ref.addValueEventListener(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot postSnapshot : dataSnapshot.getChildren()) {
Map<String,Object> users = (HashMap<String, Object>) postSnapshot.getValue();
getUserInfo(users, new ResultHandler<ArrayList<SectionData>>() {
@Override
public void onSuccess(ArrayList<SectionData> data) {
// to-do
}
});
}
}
@Override
public void onCancelled(DatabaseError databaseError) {
System.out.println("The read failed: " + databaseError.getCode());
}
});
}
void getUserInfo(final Map<String,Object> users, final ResultHandler<ArrayList<SectionData>> handler){
final ArrayList<SectionData> sdata = new ArrayList<SectionData>();
final CountDownLatch cdl1 = new CountDownLatch(users.keySet().toArray().length);
for(Map.Entry<String, Object> entry : users.entrySet()) {
String uid = entry.getKey();
final Map<String, Object> value = (HashMap<String, Object>) entry.getValue();
dataFirebase.getInfoAboutUID(uid, new ResultHandler<AUser>() { // обращение к firebase
@Override
public void onSuccess(AUser newUser) {
// to-do with sdata and newUser
// handler.onSuccess(sdata);
cdl1.countDown();
}
});
}
try {
cdl1.await();
handler.onSuccess(sdata);
} catch(InterruptedException exc) { }
}
Ответы (1 шт):
Сейчас вызов getUserInfo происходит из потока, который обслуживает события от firebase. И пока вызов onDataChange не закончится поток занят и поэтому новые события не будут обрабатываться. Получается deadlock и вызов ResultHandler, в котором сейчас cdl1.countDown() вызывается, в принципе не происходит.
Нужно вызывать hanlder напрямую:
dataFirebase.getInfoAboutUID(uid, new ResultHandler<AUser>() { // обращение к firebase
@Override
public void onSuccess(AUser newUser) {
// нужно завернуть в Handler чтоб вызов onSuccess произошел в главном обработчике
new Handler(Looper.getMainLooper()).post(() -> handler.onSuccess(sdata));
}
});