Abhimanyu
Abhimanyu

Reputation: 14837

How to convert Firebase Document Reference to Firebase Query?

I read the Firebase blog for using architecture components.
Source: https://firebase.googleblog.com/2017/12/using-android-architecture-components.html

Now to implement the same in my app, I would like to know how to convert the Firebase Document Reference to Firebase Query datatype.

Can someone help me with it?

I assume the code is not really necessary, but still providing it for better clarification.

Note:
1. I am using Firebase Firestore (the reference blog use firebase real-time database), and hence I have altered the code (referring another SO post).

FirebaseQueryLiveData.java :

public class FirebaseQueryLiveData extends LiveData<QuerySnapshot> {

//  Logging constant
private static final String TAG = "FirebaseQueryLiveData";

//  Query
private final Query query;

//  Listener
private final MyValueEventListener listener = new MyValueEventListener();
private ListenerRegistration listenerRegistration;

//  Handler
private final Handler handler = new Handler();

//  Flag to remove listener
private boolean listenerRemovePending = false;

//  Remove listener runnable
private final Runnable removeListener = new Runnable() {

    @Override
    public void run() {
        listenerRegistration.remove();
        listenerRemovePending = false;
    }
};

public FirebaseQueryLiveData(Query query) {
    this.query = query;
}

@Override
protected void onActive() {
    super.onActive();
    Log.d(TAG, "onActive");

    //  Check flag
    if (listenerRemovePending) {
        handler.removeCallbacks(removeListener);
    } else {
        listenerRegistration = query.addSnapshotListener(listener);
    }

    //  Update flag
    listenerRemovePending = false;
}

@Override
protected void onInactive() {
    super.onInactive();
    Log.d(TAG, "onInactive");

    // Listener removal is schedule on a two second delay
    handler.postDelayed(removeListener, 2000);

    //  Update flag
    listenerRemovePending = true;
}

//  Listener definition
private class MyValueEventListener implements EventListener<QuerySnapshot> {

    @Override
    public void onEvent(@Nullable QuerySnapshot queryDocumentSnapshots, @Nullable FirebaseFirestoreException e) {
        Log.d(TAG, "onEvent");

        //  Check for error
        if (e != null) {
            Log.d(TAG, "Can't listen to query snapshots: " + queryDocumentSnapshots
                    + ":::" + e.getMessage());
            return;
        }

        //  Set value if listening is successful
        setValue(queryDocumentSnapshots);
    }
}
}

View model with Firebase collection reference (which is of Query datatype according to firebase docs.)

//  Initialize Firebase variables
private static final FirebaseAuth firebaseAuth = FirebaseAuth.getInstance();
private static final FirebaseUser firebaseUser = firebaseAuth.getCurrentUser();

//  Query
private static final Query QUERY = FirebaseFirestore.getInstance().collection(COLLECTION_ORDERS)
        .whereEqualTo(ATTRIBUTE_USER_UID, Objects.requireNonNull(firebaseUser).getUid());

//  Firebase query live data
private final FirebaseQueryLiveData firebaseQueryLiveData =
        new FirebaseQueryLiveData(QUERY);

@NonNull
public LiveData<QuerySnapshot> getQuerySnapshotLiveData() {
    Log.d(TAG, "getQuerySnapshotLiveData");
    return firebaseQueryLiveData;
}

Code with Document Reference:

private static final DocumentReference documentReference = FirebaseFirestore.getInstance()
        .collection("cart")
        .document(Objects.requireNonNull(firebaseUser).getUid());

private static final Query QUERY = documentReference;

In the above code snippet :
private static final Query QUERY = documentReference;
line shows the following error:

Incompatible types.
Required: com.google.firebase.firestore.Query
Found: com.google.firebase.firestore.DocumentReference

Screenshot of the database:

enter image description here

The document Id is used to fetch a document and hence I end up with Document reference and not Collection reference.

Upvotes: 1

Views: 2435

Answers (2)

Abhimanyu
Abhimanyu

Reputation: 14837

This is not an exact answer but a doable hack, I used in my app.

Created another file for handling Document reference and used files according to the requirement.

FirebaseDocumentLiveData.java

public class FirebaseDocumentLiveData extends LiveData<DocumentSnapshot> {


    // Logging constant
    private static final String TAG = "FirebaseQueryLiveData";

    // Document Reference
    private final DocumentReference documentReference;

    // Listener
    private final MyDocumentListener listener = new MyDocumentListener();
    // Handler
    private final Handler handler = new Handler();
    private ListenerRegistration listenerRegistration;
    // Flag to remove listener
    private boolean listenerRemovePending = false;

    // Remove listener runnable
    private final Runnable removeListener = new Runnable() {

        @Override
        public void run() {
            listenerRegistration.remove();
            listenerRemovePending = false;
        }
    };


    // Constructor
    public FirebaseDocumentLiveData(DocumentReference documentReference) {
        this.documentReference = documentReference;
    }


    // On active
    @Override
    protected void onActive() {
        super.onActive();
        Log.d(TAG, "onActive");

        // Check flag
        if (listenerRemovePending) {

            // Remove callbacks
            handler.removeCallbacks(removeListener);
        } else {

            // Add listener
            listenerRegistration = documentReference.addSnapshotListener(listener);
        }

        // Update flag
        listenerRemovePending = false;
    }

    // On inactive
    @Override
    protected void onInactive() {
        super.onInactive();
        Log.d(TAG, "onInactive");

        // Listener removal is schedule on a two second delay
        handler.postDelayed(removeListener, 2000);

        // Update flag
        listenerRemovePending = true;
    }

    // Listener definition
    private class MyDocumentListener implements EventListener<DocumentSnapshot> {

        @Override
        public void onEvent(@Nullable DocumentSnapshot documentSnapshot, @Nullable FirebaseFirestoreException e) {
            Log.d(TAG, "onEvent");

            // Check for error
            if (e != null) {

                // Log
                Log.d(TAG, "Can't listen to query snapshots: " + documentSnapshot
                        + ":::" + e.getMessage());
                return;
            }

            // Set value if listening is successful
            setValue(documentSnapshot);
        }
    }
}

Upvotes: 1

Alex Mamo
Alex Mamo

Reputation: 138969

You are getting the following error:

Incompatible types. Required: com.google.firebase.firestore.Query Found: com.google.firebase.firestore.DocumentReference

At this particular line of code:

private static final Query QUERY = documentReference;

Because your are trying to assign a DocumentReference object to a Query object.

How to convert Firebase Document Reference to Firebase Query?

This is actually not possible in Java since between these two classes there is no inheritance relationship. You could assign a CollectionReference because it extends Query class but never a DocumentReference.

To get a single document, simply use DocumentReference object and never assign it another type of object.

Upvotes: 2

Related Questions