简体   繁体   中英

Return when task is completed

I'm facing a problem and I don't know how to solve it.

I'm using firebase firestore to retrieve me an exact Item. This works. The problem comes when I want the task to retun that Item in a custom class. Since firebase firestore task is asynchronous it returns null before it's completed.

Here's the code in DataAdapter class:

public Data infoFile(int position){

    DocumentReference fileRef = getInfoFile(position); //Method that retrieves the document.

    //Array to set later the Data Object that will retrieve
    final Data[] dataArray = {new Data()};

    fileRef.get().addOnCompleteListener(new OnCompleteListener<DocumentSnapshot>()
    {
        @Override
        public void onComplete(@NonNull Task<DocumentSnapshot> task)
        {

            if(task.isSuccessful()){
                DocumentSnapshot documentSnapshot = task.getResult();

                if(documentSnapshot.exists()){

                    Data data = documentSnapshot.toObject(Data.class); //Get the data
                    dataArray[0] = data; //Set data
                    System.out.println("before put bundle" + dataArray[0].getName()); //This gets the data
                    //Can't return here.

                }
            }
        }
    }).addOnFailureListener(new OnFailureListener()
    {
        @Override
        public void onFailure(@NonNull Exception e)
        {

        }
    });
    System.out.println("before put bundle and almost return " + dataArray[0].getName());

    //This returns null because task isn't completed yet.  
    return dataArray[0];
}

I've read about creating and interface and then passing the Data to the method and recieve it. But I don't know how to create/understand that. Maybe I'm wrong and that doesn't work.

Question: How can I get to return Data model when task is completed?

The last line will return null because it will get executed before the onComplete() is finished.

onComplete() on the other hand has return type void and you can't return a value in that function

You need to create a function inside the class from where you call intoFile function

public void setData(Data data){
    //Set value and use
}

And inside onComplete()

Do this

    @Override
    public void onComplete(@NonNull Task<DocumentSnapshot> task)
    {

        if(task.isSuccessful()){
            DocumentSnapshot documentSnapshot = task.getResult();

            if(documentSnapshot.exists()){

                Data data = documentSnapshot.toObject(Data.class); //Get the data
                dataArray[0] = data; //Set data
                System.out.println("before put bundle" + dataArray[0].getName()); //This gets the data
                setData(data)                }
        }
    }

Once the value is set you can perform the next operations from inside setData or you can call a function from setData which performs the next operations like this.

public void setData(Data data){
    this.data = data;
    executeNextTask(data);
}

Here you can not return data because you do not know when the data is ready to return it so you can just change the method you invoke this function:

Now I think you use the function:

Data d =  infoFile(position);
handleData(d);

change it to be:

infoFile(position,new OnCompleteListener<DocumentSnapshot>()
    {
        @Override
        public void onComplete(@NonNull Task<DocumentSnapshot> task)
        {

            if(task.isSuccessful()){
                DocumentSnapshot documentSnapshot = task.getResult();

                if(documentSnapshot.exists()){

                    Data data = documentSnapshot.toObject(Data.class); //Get the data
                    dataArray[0] = data; //Set data
                    System.out.println("before put bundle" + dataArray[0].getName());   

                    //move the handling to here.
                    handleData(data);

                }
            }
        }
    }).addOnFailureListener(new OnFailureListener()
    {
        @Override
        public void onFailure(@NonNull Exception e)
        {

        }
    });

Then change the function to:

public void infoFile(int position,OnCompleteListener<DocumentSnapshot> listener){

    DocumentReference fileRef = getInfoFile(position); //Method that retrieves the document.

    //Array to set later the Data Object that will retrieve
    final Data[] dataArray = {new Data()};

    fileRef.get().addOnCompleteListener(listener);
    System.out.println("before put bundle and almost return " + dataArray[0].getName());

}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM