#java #android #firebase #firebase-realtime-database
#java #Android #firebase #firebase-realtime-database
Вопрос:
Есть ли какой-либо способ извлечь данные из firebase, где находится код? В настоящее время у меня есть ValueEventListeners, но все они выполняются после кода под ними, что делает следующий код недействительным. Я хочу иметь возможность извлекать значение именно там, где находится код, а не позже.
На данный момент я ничего не нашел в Интернете об этом.
Хороший пример моих проблем в коде:
public void onItemClick(AdapterView<?> l, View v, final int position, long id) {
FirebaseAuth mAuth = FirebaseAuth.getInstance();
FirebaseUser user = mAuth.getCurrentUser();
final String uid = user.getUid();
databaseReference.addValueEventListener(new ValueEventListener() {
@Override
public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
cCESnapshot = dataSnapshot.child(uid).child("currChallenges").child(challengeList.get(position));
}
@Override
public void onCancelled(@NonNull DatabaseError databaseError) {
}
});
Intent intent = new Intent();
intent.setClass(this, ChallengeView.class);
intent.putExtra("snapshot", cCESnapshot.toString());
intent.putExtra("name", challengeList.get(position));
startActivity(intent);
}
Значение cCESnapshot равно нулю, потому что intent выполняется перед ValueEventListener .
Комментарии:
1. Вы должны включить создание намерения и startActivity
onDataChange
. Вы не можете запускать сетевые запросы в основном потоке / синхронизированном.2. Намерение работает нормально прямо сейчас, если только при передаче его в другой поток вызов Android не будет выполняться первым.
Ответ №1:
Это onDataChange()
асинхронный, поэтому единственный способ использовать полученные данные — внутри onDataChange()
, пример:
databaseReference.addValueEventListener(new ValueEventListener() {
@Override
public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
cCESnapshot = dataSnapshot.child(uid).child("currChallenges").child(challengeList.get(position));
Intent intent = new Intent();
intent.setClass(this, ChallengeView.class);
intent.putExtra("snapshot", cCESnapshot.toString());
intent.putExtra("name", challengeList.get(position));
startActivity(intent);
}
@Override
public void onCancelled(@NonNull DatabaseError databaseError) {
}
});
Ответ №2:
Это асинхронная операция, когда данные поступят, onDataChange
будет запущен обратный вызов. Ваш startActivty
код будет выполняться последовательно, и именно поэтому вы не получите никакого значения cCESnapshot
.
Переместите startActivity
код внутри прослушивателя.
Но будьте осторожны, потому что каждый раз onItemClick
, когда будет вызываться прослушиватель щелчков, вы будете добавлять прослушиватель событий значений. Таким образом, у вас будет несколько вызовов onDataChange
при каждом нажатии и так startActivities
далее.
Вместо этого я рекомендую использовать addListenerForSingleValueEvent
which будет срабатывать только после однократного изменения данных.