teratail posts the same question.
On Android, we are developing an app that uses Firebase (FirebaseStorage, Realtimedatabase) to display images, text, etc.
Text data is kept in the Realtimedatabase and images downloadURL is kept in the Realtimedatabase, from which the image is retrieved from FirebaseStorage.
However, when implemented, the image disappears and the image appears where the text should be displayed, causing unintended behavior.
The probable cause is that FirebaseStorage, which is used to retrieve images, and Realtimedatabase, which is used to retrieve other images, are both working asynchronously as shown below.
For example, if the fourth loop of for (DataSnapshotds...) on the realtimeDatabase side was image 1, and the Realtimedatabase was going up to the seventh loop when the acquisition of the image data (FireStorage side) was completed, the messageDataBean on the fourth loop would be updated.
To prevent this, for example, after you have finished retrieving the image you started retrieving in the fourth loop, you need to install it in the image field of the fourth loop List (messageDataBean) and the image you tried to retrieve in the eighth loop List.
Also, I tried to keep the order of image acquisition by locking each loop by referring to the page below, but it didn't work.
Java Exclusive Control (Lock) Class Summary - Qiita
page called java.concurrent.locks.Lock,Condition in
DatabaseReference ref=;
Bitmap imgBitmap;
ArrayList<MessageDataBean>messageDataBean=newArrayList<MessageDataBean>();;
// Read DB (Realtimedatabase except image)
ref.addValueEventListener(){
@ Override
public void onDataChange(@NonNullDataSnapshotdataSnapshot){
for (DataSnapshot: dataSnapshot.getChildren()) {
String txtData1;
String txtData2;
String msgType=ds.child("type").getValue();
For if(msgType.equals("txt"){// text:
txtData1 = ds.child("txt1").getValue();
txtData2=ds.child("txt2").getValue();
} else if(msgType.equals("img")) {// For Images
// Image Download URL
String downloadURL = String.valueOf(ds.child("img_dl_url").getValue());
StorageReference images=FirebaseStorage.getInstance().getReferenceFromUrl(downloadURL);
// Specify the maximum download size
final long ONE_MEGABYTE = 1024*1024;
images.getBytes(ONE_MEGABYTE).addOnSuccessListener(newOnSuccessListener<byte[]>(){
@ Override
public void onSuccess(byte[]bytes) {
// Image Download Successful
imgBitmap = OtherUtils.createBitmap (bytes, 1024, 1024);
}
}).addOnFailureListener(newOnFailureListener(){
@ Override
public void onFailure(@NonNullException exception) {
// Image download failure
}
});
}
MessageDataBean messageDataBean=new MessageDataBean(
txtData1,
txtData2,
imgBitmap,
);
messageDataBeanList.add(messageDataBean);
show(messageDataBeanList);// Display Update Process
}
}
@ Override
public void onCancelled(@NonNullDatabaseErrordatabaseError) {
}
});
Hello, nice to meet you.I saw the code.
Let me give you a point of concern.
At this point, it would be better to read directly from the URL information to the view in a library such as Glide
.
https://qiita.com/hotchemi/items/375d63261f2eed2b18e1
I couldn't guess how to display it on the screen from the code you gave me.Depending on the view you use on Android, the implementation method often follows a certain form.FriendlyChat in codelab deals with real-time database processing and image display from Storage, so it may be helpful.
https://codelabs.developers.google.com/codelabs/firebase-android/ #1
https://github.com/firebase/friendlychat-android
At this point, it would be better to read directly from the URL information to the view in a library such as Glide
instead of loading the image.
https://qiita.com/hotchemi/items/375d63261f2eed2b18e1
I couldn't guess how to display it on the screen from the code you gave me.Depending on the view you use on Android, the implementation method often follows a certain form.FriendlyChat in codelab deals with real-time database processing and image display from Storage, so it may be helpful.
https://codelabs.developers.google.com/codelabs/firebase-android/ #1
https://github.com/firebase/friendlychat-android
add
I haven't used it very often, but it seems that I can wait for the image to be downloaded without going through Listener using the following methods:Getting the getBytes return value Task to synchronize with Tasks.wait and complete the read in for loop may be possible if the code around the display is not fiddling.
https://developers.google.com/android/guides/tasks
Firebase itself is intended for asynchronous implementation.I think it is possible to achieve synchronization by fixing the order of calls in Tasks or directly using RestAPI, but I recommend that you avoid it as much as possible and trace the implementation provided by Google.
https://developers-jp.googleblog.com/2016/09/become-a-firebase-taskmaster-part-1.html
https://stackoverflow.com/questions/31700830/is-it-possible-to-synchronously-load-data-from-firebase
© 2024 OneMinuteCode. All rights reserved.