我有一个包含照片的Firebase存储空间。 我按名称1,2,3等组织照片...... 我试图获取所有照片下载网址,因此将来我会将它们输入到URL的Arraylist中并使用Glide将它们呈现在照片库中(这就是为什么我只是在寻找URLS)
我正在寻找一种方法,只有在调用onSucsess时才会给我Urls,当调用onFailure时(因为没有更多照片)我希望循环结束。
我正在尝试使用Firebase的getDownloadUrl方法,并添加了一个布尔值,当调用onFailure时会触发false。 并增加我的photoOrder int,从1开始,然后改变所选照片的路径。
public class Photopackges extends AppCompatActivity {
public static boolean shouldRun = true;
public static final String TAG = "debug";
public static int photoOrder = 1;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_photopackges);
//just normal firebase setup
FirebaseStorage storage = FirebaseStorage.getInstance();
// while shouldRun boolean is true keep going , until it will be defined false
while (shouldRun == true) {
// define my Firebase storage path,which contain one folder called "test" and three photos 1.jpg,2.jpg,3.jpg
// the number of the photo is represented in the photoOrder int.
String storagePath = "test/" + String.valueOf(photoOrder) + ".jpg";
StorageReference ref = storage.getReference().child(storagePath);
try {
ref.getDownloadUrl().addOnSuccessListener(new OnSuccessListener<Uri>() {
@Override
public void onSuccess(Uri uri) {
// trying to define that if the action was successful , keep on going.
shouldRun = true;
Log.e(TAG, "sucsess! " + uri);
}
}).addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(@NonNull Exception e) {
// trying to define that if the action has failed , stop.
shouldRun = false;
Log.e(TAG, "Fail! " + e);
}
});
} catch (Exception e) {
Log.e(TAG, "Error! " + e);
break;
}
//increment the photoOrder so it will go to the next path.
photoOrder++;
Log.e(TAG,"value of photoOrder "+photoOrder);
}
}
}
日志 -
我没有问题,他在得到答案之前发出了更多请求。 我只是需要他在它到达时停止
StorageException:对象在位置不存在。
我猜测必须有一种更简单的方法来使用firebase来获取所有存储空间。
感谢您的帮助!
答案 0 :(得分:3)
好的,所以经过很多尝试后我可以使用wait()和notify()方法。
现在,我可以使用FirebaseStorage中所有照片的下载网址来获取 ArrayList ,其中可能包含未知数量的照片。 注意到这只是因为在我进入我的storge之前我必须重命名它们(1,2,3 ......等)。
为此,您需要:
我能够得到这个Logcat,这就是我想要的 See Log
public static final String TAG = "eyaldebug";
public static PathGenerator pathGenerator;
public static ArrayList<String>photoURLs;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_photopackges);
//Initialize the whole process
photoURLs = new ArrayList<>();
pathGenerator = new PathGenerator();
new UrlProducer(pathGenerator);
}
/**
* This class contains the GeneratePaths method,which responsible
* of making new paths.
* Also we have a simple set - get methods of the booleans.
*/
class PathGenerator {
//start photo number
int photoNumber = 0;
//boolean that indicates if the path has been used already or not.
boolean pathIsTaken = false;
//our storage path.
String path;
/**
* This method will generate a new path.
* while path is taken , wait because we didn't use it yet.
*
* @param photoNumber
*/
public synchronized String generatePath(int photoNumber) {
while (pathIsTaken)
{
try {wait();} catch (Exception e) {}
}
this.photoNumber = photoNumber;
path = "test/" + String.valueOf(photoNumber) + ".jpg";
pathIsTaken = true;
Log.e("eyaldebug", "path is : " + path);
return path;
}
/**
* Simple set method.
* @param value
*/
public synchronized void setPathisSet(boolean value)
{
this.pathIsTaken = value;
}
/**
* Unfreeze the thread, we call this method after onSucsess.
*/
public synchronized void unfreeze( )
{
notifyAll();
}
}
/**
* Our URLProducer calls will take the paths,and will
* send HTTP request to the storage that we'll get a
* download URL returned.
* later we'll be using Glide\Picasso to display those images.
*/
class UrlProducer implements Runnable {
PathGenerator mPathGenerator;
//initialize a String type ArrayList which will contain our URLS.
public ArrayList<String>photoURLs = new ArrayList<>();
//constructor that will be called in the activity
public UrlProducer(PathGenerator mPathGenerator) {
this.mPathGenerator = mPathGenerator;
Thread b = new Thread(this, "UrlProducer");
b.start();
}
/**
* Here we a simple download URL method using FirebaseStorage.
* for the documentation for FirebaseStoarge download go to :
*
* https://firebase.google.com/docs/storage/android/download-files
*
* IF the task was successful we UNfreeze the threads so it will
* keep sending us new URLS.
* IF the onFailure was called the stroage is must likely empty and
* we should stop trying to get new photos.
*/
@Override
public void run() {
int photoNumber =0 ;
while (true) {
photoNumber ++;
try {
FirebaseStorage storage = FirebaseStorage.getInstance();
StorageReference ref = storage.getReference();
ref.child(pathGenerator.generatePath(photoNumber)).getDownloadUrl().addOnSuccessListener(new OnSuccessListener<Uri>() {
@Override
public void onSuccess(Uri uri) {
Log.e(TAG, "Success! " + uri);
//add the URL into the ArrayList
photoURLs.add(String.valueOf(uri));
//tell the generate method that the path has been used.
pathGenerator.setPathisSet(false);
//Unfreeze the thread so it will continue generate new paths.
pathGenerator.unfreeze();
}
}).addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(@NonNull Exception e) {
//When onFailure is called shutdown,and output the given ArrayList.
Log.e(TAG,"onFailure was called , storage is empty!");
Log.e(TAG,"----------------------------------------");
for(String singleUrl :photoURLs)
{
Log.e(TAG,""+singleUrl) ;
}
}
});
}catch (Exception e){e.printStackTrace();}
}
}
}
答案 1 :(得分:0)
嗯,问题是由于调用 ref.getDownloadUrl()是异步的。因此,当您调用第一个onFailure方法时,已经有许多其他调用异步方法,因为您的循环运行得更快,并且不会等待前一次调用的响应。
所以我的建议是你应该将你的URL存储在firebase RealtimeDatabase中并获取这些URL然后用滑动加载它们。
如果您想了解有关处理网址列表的信息,可以查看文档 https://firebase.google.com/docs/database/android/lists-of-data