简体   繁体   中英

How to fetch data from multiple Firestore collections into one RecyclerView?

Here is my delivery application, here I am saving the delivery boy's check-in and check-out location into Firestore with a timestamp, when the delivery boy delivers the product and when he check-out from the house. here is my code, this is my showing data into recyclerView class where I am showing the check-in and check-out data in one CardView. This is my java class

package com.example.location.Activites;

import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;

import android.os.Bundle;

import com.example.location.AdapterClass.AdapterClass;
import com.example.location.AdapterClass.CheckOutAdapterClass;
import com.example.location.ModelClasses.DataModelClass;
import com.example.location.R;
import com.firebase.ui.firestore.FirestoreRecyclerOptions;
import com.google.firebase.auth.FirebaseAuth;
import com.google.firebase.auth.FirebaseUser;
import com.google.firebase.firestore.CollectionReference;
import com.google.firebase.firestore.FirebaseFirestore;
import com.google.firebase.firestore.Query;

public class LastVisitedLocationActivity extends AppCompatActivity {

    private FirebaseFirestore db = FirebaseFirestore.getInstance();
    FirebaseUser mUser = FirebaseAuth.getInstance().getCurrentUser();
    String userID = mUser.getUid();
    private CollectionReference collectionReference = db.collection("UserLocation").document(userID).collection("CheckIn");
    private CollectionReference collectionReference1= db.collection("UserLocation").document(userID).collection("CheckOut");

    private RecyclerView recyclerView ;
    private AdapterClass adapterClass;
    private CheckOutAdapterClass checkOutAdapterClass;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_last_visited_location);

        recyclerView = findViewById(R.id.RecyclerView);

        setupRecyclerView();
        setupRecyclerView1();
    }

    private void setupRecyclerView() {
        Query query1 = collectionReference.orderBy("timestamp",Query.Direction.DESCENDING);
        FirestoreRecyclerOptions<DataModelClass> options = new FirestoreRecyclerOptions.Builder<DataModelClass>()
                .setQuery(query1,DataModelClass.class).build();

        adapterClass  =  new AdapterClass(options);

        recyclerView.setHasFixedSize(true);
        recyclerView.setLayoutManager(new LinearLayoutManager(this));
        recyclerView.setAdapter(adapterClass);

    }

    private void setupRecyclerView1() {
        Query query2 = collectionReference1.orderBy("timestamp");
        FirestoreRecyclerOptions<DataModelClass> options = new FirestoreRecyclerOptions.Builder<DataModelClass>()
                .setQuery(query2,DataModelClass.class).build();

        checkOutAdapterClass =  new CheckOutAdapterClass(options);

        recyclerView.setHasFixedSize(true);
        recyclerView.setLayoutManager(new LinearLayoutManager(this));
        recyclerView.setAdapter(checkOutAdapterClass);

    }



    @Override
    protected void onStart() {
        super.onStart();
        adapterClass.startListening();
        checkOutAdapterClass.startListening();
    }

    @Override
    protected void onStop() {
        super.onStop();
        adapterClass.stopListening();
        checkOutAdapterClass.stopListening();
    }
} 

this is my xml class

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/item_linerLayout"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:padding="2dp">

    <androidx.cardview.widget.CardView
        android:id="@+id/cardView"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginStart="5dp"
        android:layout_marginTop="5dp"
        android:layout_marginEnd="5dp"
        android:layout_marginBottom="5dp"
        app:cardCornerRadius="10dp"
        app:cardElevation="10dp"
        app:strokeColor="@color/white"
        app:strokeWidth="2dp">


        <androidx.constraintlayout.widget.ConstraintLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginStart="6dp">

            <TextView
                android:id="@+id/recycler_CheckInlatitudeLongitude"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginStart="2dp"
                android:fontFamily="@font/amarante"
                android:paddingStart="15dp"
                android:paddingTop="10dp"
                android:paddingEnd="15dp"
                android:paddingBottom="10dp"
                android:text="Latitude and Longitude"
                android:textColor="@color/black"
                android:textSize="14sp"
                android:textStyle="bold"
                app:layout_constraintEnd_toEndOf="parent"
                app:layout_constraintHorizontal_bias="0.0"
                app:layout_constraintStart_toStartOf="parent"
                app:layout_constraintTop_toBottomOf="@+id/textView" />

            <TextView
                android:id="@+id/recyclerView_CheckIndateAndTime"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginStart="2dp"
                android:fontFamily="@font/amarante"
                android:paddingStart="15dp"
                android:paddingTop="10dp"
                android:paddingEnd="15dp"
                android:paddingBottom="10dp"
                android:text="Date and time"
                android:textColor="@color/black"
                android:textSize="14sp"
                app:layout_constraintEnd_toEndOf="parent"
                app:layout_constraintHorizontal_bias="0.0"
                app:layout_constraintStart_toStartOf="@+id/recycler_CheckInlatitudeLongitude"
                app:layout_constraintTop_toBottomOf="@+id/recycler_CheckInlatitudeLongitude" />

            <TextView
                android:id="@+id/textView"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginStart="2dp"
                android:layout_marginTop="8dp"
                android:text="Check-In"
                android:textSize="18sp"
                android:textStyle="bold"
                app:layout_constraintEnd_toEndOf="parent"
                app:layout_constraintHorizontal_bias="0.0"
                app:layout_constraintStart_toStartOf="@+id/recycler_CheckInlatitudeLongitude"
                app:layout_constraintTop_toTopOf="parent"
                tools:text="Check-In" />

            <TextView
                android:id="@+id/recycler_CheckOutlatitudeLongitude"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginStart="2dp"
                android:fontFamily="@font/amarante"
                android:paddingStart="15dp"
                android:paddingTop="10dp"
                android:paddingEnd="15dp"
                android:paddingBottom="10dp"
                android:text="Latitude and Longitude"
                android:textColor="@color/black"
                android:textSize="14sp"
                android:textStyle="bold"
                app:layout_constraintEnd_toEndOf="parent"
                app:layout_constraintHorizontal_bias="1.0"
                app:layout_constraintStart_toStartOf="parent"
                app:layout_constraintTop_toBottomOf="@+id/textView3" />

            <TextView
                android:id="@+id/recyclerView_CheckOutdateAndTime"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginStart="2dp"
                android:fontFamily="@font/amarante"
                android:paddingStart="15dp"
                android:paddingTop="10dp"
                android:paddingEnd="15dp"
                android:paddingBottom="10dp"
                android:text="Date and time"
                android:textColor="@color/black"
                android:textSize="14sp"
                app:layout_constraintEnd_toEndOf="parent"
                app:layout_constraintHorizontal_bias="0.0"
                app:layout_constraintStart_toStartOf="@+id/recycler_CheckInlatitudeLongitude"
                app:layout_constraintTop_toBottomOf="@+id/recycler_CheckOutlatitudeLongitude" />

            <TextView
                android:id="@+id/textView3"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginTop="8dp"
                android:text="Check-out"
                android:textSize="18sp"
                android:textStyle="bold"
                app:layout_constraintEnd_toEndOf="parent"
                app:layout_constraintHorizontal_bias="0.006"
                app:layout_constraintStart_toStartOf="@+id/recycler_CheckOutlatitudeLongitude"
                app:layout_constraintTop_toBottomOf="@+id/recyclerView_CheckIndateAndTime"
                tools:text="Check-Out" />

        </androidx.constraintlayout.widget.ConstraintLayout>

    </androidx.cardview.widget.CardView>
</RelativeLayout>

So the data into firestore is like:- userLocation(collection) --> userAuthID(document) -->CheckIn(collection)-->here i am saving location of check-in CheckOut(Collection)--> here i am saving location of check-out.

Have you seen https://www.codegrepper.com/code-examples/whatever/two+arraylist+one+recyclerview+adapter ?

  1. First way: Here it gets two lists in the constructor. and It shows the lists after each other. But If you want to show the data as a sorted list by time in a RecyclerView, I suggest you use the second way.

  2. Second way: Create a single sorted list by mixing those Check-In and Check-Out lists in Asc or Dec order by time. and pass it to the adapter easily.

These are the ways that you can handle it. If there were any problem ask it again.

There is no way you can pass two different queries "collectionReference" and "collectionReference1" to a single instance of "FirestoreRecyclerOptions", only one is allowed. There are two ways in which you can solve this. The first solution is to get() the result of both queries and save each one of them into an object of type Task , and then simply use Tasks.whenAllSuccess(Task...<?> tasks) , as explained in my answer from the following post:

In this case, you'll lose Firebase-UI's features. It's not perfect, but it will do the trick.

The second approach would be to duplicate the data, meaning that you can create a new collection that will contain the documents from both collections, and then pass that "CollectionReference" object to the FirestoreRecyclerOptions's "setQuery()" method.

This technique is called "denormalization" and is quite common practice when it comes to Firebase. So we often duplicate data in NoSQL databases, to suit queries that may not be possible otherwise. For a better understanding, I recommend you see this video, Denormalization is normal with the Firebase Database . It's for the Firebase Realtime database but the same principles apply to Cloud Firestore.

For more info, please also check my answer from the following post:

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