1

I need a function that checks if a value exists or not in my firebase realtime database. I tried to write the code below:

    public boolean esiste(String desc, DatabaseReference meseref){

        boolean exists = false;
        meseref.addListenerForSingleValueEvent(new ValueEventListener() {
            @Override
            public void onDataChange(@NonNull DataSnapshot snapshot) {
                if(snapshot.child(desc).exists()){
                    exists = true;
                }
            }

            @Override
            public void onCancelled(@NonNull DatabaseError error) {

            }
        });

        return exists;
    }

Maybe it is not the best way, but it is seems very simple for me (I am not an expert programmer). The problem is that compiler says that "Variable 'exists' is accessed from within inner class, needs to be final or effectively final", and I have an error.

So, how can I make a function that checks if the value exists or not?

Thank you so much

Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807
newbieprog
  • 21
  • 6
  • 2
    This function isn't going to work, because it doesn't wait for the listener to actually finish. If you created something like a `CompletableFuture`, completed it in the listener, and returned `get()` on that `CF`, you'd at least have something that works even if it blocks. – Louis Wasserman Jul 26 '22 at 16:54
  • This [resource](https://www.youtube.com/watch?v=OvDZVV5CbQg) and this [resource](https://medium.com/firebase-tips-tricks/how-to-read-data-from-firebase-realtime-database-using-get-269ef3e179c5) might also help. – Alex Mamo Jul 27 '22 at 08:21

1 Answers1

2

You have two separate problems, the compiler error and a conceptual error. To get your desired result, you need to restructure the code to fix the conceptual error, but you should also try to understand the compiler error in the existing code.

For the compiler error, see the explanation of effectively final variables in anonymous inner classes in this question.

(You didn't provide imports in your example, so I am guessing about the framework you are using in the links I provide below).

For the conceptual error, according to the documentation, the purpose of the addListenerForSingleValueEvent method is to register a listener that will be notified (asynchronously, i.e., in another thread) if the value referred to by the DatabaseReference changes. Even if your code compiled, registering the listener would return immediately, and the value of your exists variable would depend on whether the listener happened to update the value of the variable in the very short time before your code reached the return statement.

Instead, you need to check the value directly. For this, I think you need the get method. This method is also asynchronous, but works differently. It gives you a Task, and you need to wait for the Task to complete (using the Tasks.await) before retrieving its value.

The code should look something like this:

    public boolean esiste(String desc, DatabaseReference meseref){

        Task<DataSnapshot> task = meseref.get();
        DataSnapshot dataSnapshot = Tasks.await(task);
        return snapshot.child(desc).exists();
    }