How to Display Data from Firestore in a Recyclerview With Android

Display Data from Firestore on a RecyclerView using Kotlin

You need to provide default values to your model fields. Firestore will assign that default value to the field in case that particular field is missing from the document snapshot.

data class Proyecto(
val alcances: String = "",
val alumnos: HashMap<String, Any> = hashMapOf(),
val areasConoc: String = "",
val asignaturas: String = "",
val cliente: String = "",
val colaboradores: String = "",
val compDes: String = "",
val compPrev: String = "",
val coordinador: String = "",
val departamentos: String = "",
val impacto: String = "",
val institucion: String = "",
val justificacion: String = "",
val limityrest: String = "",
val materiaEje: String = "",
val periodo: HashMap<String, Any> = hashMapOf(),
val plan: String = "",
val planteamiento: String = "",
val profeResp: String = "",
val tipoejec: String = "",
val tituloproyecto: String = ""
)

Also, it is recommended to use Kotlin's immutable Map instead of Java's HashMap.

How to display data from Firestore in a RecyclerView with Android?

Assuming you have a Firestore database structure that looks like this:

Firestore-root
|
--- products (collection)
|
--- documentIdOne (document)
| |
| --- productName: "Milk"
|
--- documentIdTwo (document)
| |
| --- productName: "Soy Milk"
|
--- documentIdThree (document)
|
--- productName: "Bacon"

A model class that looks also like this:

public class ProductModel {
private String productName;

public ProductModel() {}

public ProductModel(String productName) {this.productName = productName;}

public String getProductName() {return productName;}
}

And a .XML file that contains a RecyclerView which also looks like this:

<android.support.v7.widget.RecyclerView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/recycler_view"/>

To display all the product names, please follow the next steps.

First, you need to find the RecyclerView in your activity and set the LinearLayoutManager like this:

RecyclerView recyclerView = findViewById(R.id.recycler_view);
recyclerView.setLayoutManager(new LinearLayoutManager(this));

Then you need to create the root reference of your Firestore database and a Query object like this:

FirebaseFirestore rootRef = FirebaseFirestore.getInstance();
Query query = rootRef.collection("products")
.orderBy("productName", Query.Direction.ASCENDING);

Then you'll have to create a FirestoreRecyclerOptions object like this:

FirestoreRecyclerOptions<ProductModel> options = new FirestoreRecyclerOptions.Builder<ProductModel>()
.setQuery(query, ProductModel.class)
.build();

In your activity class, create a holder class that looks like this:

private class ProductViewHolder extends RecyclerView.ViewHolder {
private View view;

ProductViewHolder(View itemView) {
super(itemView);
view = itemView;
}

void setProductName(String productName) {
TextView textView = view.findViewById(R.id.text_view);
textView.setText(productName);
}
}

Then create an adapter which is declared as global:

private FirestoreRecyclerAdapter<ProductModel, ProductViewHolder> adapter;

And instantiate it in your activity like this:

adapter = new FirestoreRecyclerAdapter<ProductModel, ProductViewHolder>(options) {
@Override
protected void onBindViewHolder(@NonNull holder productViewHolder, int position, @NonNull ProductModel productModel) {
holder.setProductName(productModel.getProductName());
}

@NonNull
@Override
public ProductViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_product, parent, false);
return new ProductViewHolder(view);
}
};
recyclerView.setAdapter(adapter);

In the end, don't forget to override the following two methods and start listening for changes:

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

@Override
protected void onStop() {
super.onStop();

if (adapter != null) {
adapter.stopListening();
}
}

The result is this:

Sample Image

Edit:

If you want to display a toast message when the user clicks on an item, please add the following lines of code inside the setProductName() method from the ProductViewHolder class:

textView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Toast.makeText(getApplicationContext(), productName, Toast.LENGTH_SHORT).show();
}
});

Data from Firestore is not displayed in RecyclerView

I have set my database rule to allow read, write: if true; but still didn't work.

If you set:

allow read, write: if true;

In your Security Rules, it means that you allow both, read and write operations, to be performed in your Cloud Firestore database. But this is not the reason why your RecylerView is empty. When you try to map a document from Firestore into an object of your "ModelClass", the name of the fields that exist in your class must match the name of your properties that exist in your database. Unfortunately, in your case, the fields don't match. See, the fields in your class start with lowercase, while in the database start with a capital letter, which is not correct.

To solve this, you have two options, you either change the name of your properties in the database to match the one in the class, or you can use an annotation in front of the getters. For example, if you have a field called "date" and the property in the database is called "Date" (upper-case D), your getter should look like this:

@PropertyName("Date")
public String getDate() {
return date;
}

In this way, you tell the compiler to look for a property called "Date" and not "date".

Because you are using public getters, don't also forget to set the fields in your class as private. If you want to keep them, for example, public, the getters are not needed. You can set the values directly on the public fields. So a minimum class declaration might look like this:

public class ModelClass {
public String date, time, text, divider;
}

Please also note, that the public no-argument constructor is also not needed, as it is provided by the compiler.

RecyclerView is not showing data from Firestore

I think the problem is that the listener is triggered after the adapter is created and set. You need to explicitly call myCompanyAdapter.notifyDataSetChanged after the data list is modified.

Please try the below code

 recyclerView = findViewById(R.id.companyFeed_RecyclerView_CompanyList);
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(new LinearLayoutManager(this));

ArrayList<Company> myCompanyData = new ArrayList<>();

CompanyAdapter myCompanyAdapter = new CompanyAdapter(myCompanyData, CompanyFeedActivity.this);
recyclerView.setAdapter(myCompanyAdapter);
myCompanyData.add(new Company("Company marc","trustworthy",null));
db.getFirestore().collection("companies").addSnapshotListener((value, error) -> {
assert value !=null;
for (QueryDocumentSnapshot snapshot : value) {
Company c = Deserialization.deserializeCompany(snapshot);
myCompanyData.add(new Company(c.getName(),c.getDescription(),null));
System.out.println("company: " + myCompanyData.get(1).getName());
}
myCompanyAdapter.notifyDataSetChanged()
});

android - how to display the array of object from Cloud FireStore in the RecyclerView

You need to two different classes. The first one would be, for example, ViewOrderModel class, which will hold the fields as address, currentTime, documentID, and so on.

And the second one called Product:

class Product {
String documentID, productName;
int productPrice, totalPrice, totalQuantity;
}

Which will hold the properties corresponding to the object that exists in the itemList. So your ViewOrderModel class should look like this:

public class ViewOrderModel implements Serializable {
String userName,phoneNumber,currentTime,address,documentID,productName;
List<Product> itemList;
br>}

Firestore data doesn't show up in RecyclerView

You aren't getting anything from the database because the name of your fields inside the Upload class are different than the name of the fields that exist in the database. Both should match. To solve this, you either change all the name of your fields inside your Upload class to match the properties that exist in the database or your can use annotations. Because I see that you are using private fields and public getters, you should use the PropertyName annotation only in front of the getter, for instance your getName() getter should look like this:

@PropertyName("name")
public String getName() {
return mName;
}


Related Topics



Leave a reply



Submit