Android uygulamamda bir WebView'un parçalarını Firebase üzerinden bağlanan bir eşden aldığım verilerle güncellemeye çalışıyorum. Bunun için gerekli verileri geri getirecek engelleme işlemlerini yürütmek yararlı olabilir. Örneğin, başka bir sohbet katılımcısının push.setValue() öğesinden önce bir şey yazmasını bekleyecek olan Sohbet örneğinin uygulanması. Firebase ile böyle bir davranış mümkün mü?Verileri Firebase'den eşzamanlı olarak yüklemek mümkün mü?
cevap
Düzenli bir JVM'de, bunu düzenli Java senkronizasyon ilkelleriyle gerçekleştirirsiniz. Örneğin
:
// create a java.util.concurrent.Semaphore with 0 initial permits
final Semaphore semaphore = new Semaphore(0);
// attach a value listener to a Firebase reference
ref.addValueEventListener(new ValueEventListener() {
// onDataChange will execute when the current value loaded and whenever it changes
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
// TODO: do whatever you need to do with the dataSnapshot
// tell the caller that we're done
semaphore.release();
}
@Override
public void onCancelled(FirebaseError firebaseError) {
}
});
// wait until the onDataChange callback has released the semaphore
semaphore.acquire();
// send our response message
ref.push().setValue("Oh really? Here is what I think of that");
Ama bu Android'de çalışmayacaktır. Ve bu iyi bir şey, çünkü bu tür bir engelleme yaklaşımını kullanıcı arayüzünü etkileyen herhangi bir şeyde kullanmak kötü bir fikir. Bu kodun etrafta yatan tek sebebi, bir birim testinde ihtiyacım olduğu için.
Gerçek kullanıcılara yönelik kodda, olay odaklı bir yaklaşıma gitmelisiniz.
// attach a value listener to a Firebase reference
ref.addValueEventListener(new ValueEventListener() {
// onDataChange will execute when the current value loaded and whenever it changes
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
// TODO: do whatever you need to do with the dataSnapshot
// send our response message
ref.push().setValue("Oh really? Here is what I think of that!");
}
@Override
public void onCancelled(FirebaseError firebaseError) {
}
});
net sonuç tam olarak aynıdır, ancak bu kodu: Yani "veri gelip sonra benim mesaj göndermek için beklemek" yerine, ben "verileri geldiğinde, benim mesaj göndermek edeceğini" senkronizasyon gerektirmez ve Android'de engellenmez. Paket com.google.android.gms.tasks adresindeki
;
Tasks.await (taskFromFirebase);
Bu aslında kabul edilen bir cevap olmalıdır. –
Gerçekten teşekkürler, ben de bunu arıyordum; Ancak bu, "gerekli verileri * geri verecek olan engelleme işlemlerini yürüt" ü nasıl çözer? Olay dinleyicileri Görevler değil, bunu nasıl yapıyorsunuz? –
http://stackoverflow.com/questions/37215071/firebase-android-how-to-read-from-different-references-sequlyential –
Veri eşzamanlı olarak başka bir veri alma yöntemi ile geldim. Ön koşul, kullanıcı arabiriminde olmamalıdır.
final TaskCompletionSource<List<Objects>> tcs = new TaskCompletionSource<>();
firebaseDatabase.getReference().child("objects").addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
Mapper<DataSnapshot, List<Object>> mapper = new SnapshotToObjects();
tcs.setResult(mapper.map(dataSnapshot));
}
@Override
public void onCancelled(DatabaseError databaseError) {
tcs.setException(databaseError.toException());
}
});
Task<List<Object>> t = tcs.getTask();
try {
Tasks.await(t);
} catch (ExecutionException | InterruptedException e) {
t = Tasks.forException(e);
}
if(t.isSuccessful()) {
List<Object> result = t.getResult();
}
Çözümü test ettim ve iyi çalışıyor, ama lütfen yanlış olduğumu kanıtlayın!
Bu yeni SnapshotToObjects(); herhangi bir yerleşik sınıf mı yoksa kendi sınıfınızı mı oluşturdunuz? eğer kendi sınıfınız varsa, bunu ve onun parametresini ( –
) söyleyebilirsiniz. Bu benim tarafımdan uygulanır ve DataSnapshot -> List
Bu yöntemi –
Teşekkürler Frank! Engelleme ve olay odaklı yaklaşıma katılıyorum. Ancak, WebView'e birden fazla güncelleme yapmak zorundayım, bir WebView.loadDataWithBaseURL() işlevi ve HTTP istekleri (WebView'ın gerçekleştirdiği) de aynı şekilde engelleniyor. WebView'ın kendisi yerine bunu yapmamın nedeni, sunucunun uygulamaya erişemeyeceğidir ve Firebase'i bir "tünel" olarak kullanıyorum. Daha iyi bir çözüm, çok takdir edilecektir. Ayrıca, engelleme bölümü WebView her güncellemede her seferinde tetiklenebilecek bir olayın içinde ise Semaphore çözümü başarısız olmaz mı? – Dani
Yukarıdaki snippet'in verdiğiniz Sohbet örneğini ele aldığından eminim. Büyük/küçük harf kullanımı aslında farklıysa, lütfen bir http://stackoverflow.com/help/mcve sağlayın. Kod, haftanın her günü bu kodun bir açıklamasını atıyor. –
Evet, gerçekten çalışıyor! Teşekkürler @Frank! – Dani