0

I'm having a problem and I don't know how to solve it. I'm learning Android for myself and now I'm using a Navigation Drawer to interact with a part of my application. What I want is when I choose the questionItem from the NavigationActivity I want to return a View depending on a boolean variable stored in the Firebase Firestore. I know that queries on Firebase are asynchronous and that's why the no_question layout is returned always, even if the value of the variable stored is true. But I don't know how to solve it, and I will be really grateful if someone help me to find a solution. I've tried lots of solutions like using threads to synchronize or sleeping the main thread but it's not working.

Here is my code:

public class QuestionFragment extends Fragment {

    private View root;

    private boolean[] question_act = new boolean[1];

    public View onCreateView(@NonNull LayoutInflater inflater,
                         ViewGroup container, Bundle savedInstanceState) {

        isQuestion_act(new Callback() {
            @Override
            public void activacioRebuda(final boolean qNova) {
                question_act[0] = qNova;
            }
        });

        if (question_act[0]) root = inflater.inflate(R.layout.fragment_question, container, false);
        else root = inflater.inflate(R.layout.fragment_noquestion, container, false);

        return root;
    }

    public interface Callback {
        void activacioRebuda(final boolean question);
    }

    private void isQuestion_act(Callback callback) {

            FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser();
            assert user != null;
            String id = user.getUid();

            FirebaseFirestore db = FirebaseFirestore.getInstance();

            db.collection("players")
                    .whereEqualTo("Id", id).whereEqualTo("Question_act", true)
                    .get()
                    .addOnCompleteListener(task -> {
                        if (task.isSuccessful()) {
                            for (QueryDocumentSnapshot document : Objects.requireNonNull(task.getResult())) {
                                Log.d(TAG, document.getId() + " => " + document.getData());
                                boolean q = document.getBoolean("Question_act");
                                Log.d(TAG, " question " + q);
                                if (callback != null) {
                                    callback.activacioRebuda(q);
                                }
                            }
                        } else {
                            Log.w(TAG, "Error getting documents.", task.getException());
                            Toast.makeText(getActivity(), "User does not exist", Toast.LENGTH_SHORT).show();
                        }
                    });
    }
}
Alex Mamo
  • 130,605
  • 17
  • 163
  • 193

1 Answers1

0

Simply assigning question_act[0] = qNova; doesn't make any difference. As you already mentioned in your question, Firebase API is asynchronous, so using the value of qNova outside the callback will never work.

The only option that you have is to wait for the data by using the value of qNova only inside the activacioRebuda() method, as you are pretty sure that the operation of getting the data from the database is 100% complete.

For a working solution, please see my answer from the following post:

Alex Mamo
  • 130,605
  • 17
  • 163
  • 193
  • Alex, thank you for your answer, but it's not solving at all my problem. How can I update the variable "root", that is a View, inside activacioRebuda() and return then in the onCreateView? – Bernat Puig Font Apr 05 '20 at 17:32
  • My answer did not solve all the problems, right? But the first one is solved, right? – Alex Mamo Apr 05 '20 at 17:52
  • Besides that, that's a totally different question. If you have a hard time with the second issue, please post a new question using its own [MCVE](https://stackoverflow.com/help/mcve), so I and other Firebase developers can help you. – Alex Mamo Apr 05 '20 at 17:53