After being successful with writing and reading data from Firestore, I am now trying to display that data in a RecyclerView by utilizing FirestoreRecyclerAdapter. However, in my onBindViewHolder, where I'm trying to set a textView with data from the database, I'm getting a NullPointerException, where my Client name is null.
Here is my FirestoreAdapter class:
public class FirestoreAdapter extends FirestoreRecyclerAdapter<ServiceOrder, FirestoreAdapter.ViewHolder> {
public FirestoreAdapter(@NonNull FirestoreRecyclerOptions<ServiceOrder> options) {
super(options);
}
@Override
protected void onBindViewHolder(@NonNull ViewHolder holder, int position, @NonNull ServiceOrder model) {
holder.osIdItem.setText(String.valueOf(getItem(position).getId()));
holder.osClientItem.setText(getItem(position).getClient().getName()); //Line with error
holder.osDateItem.setText(getItem(position).getDate());
holder.osValueItem.setText(String.valueOf(getItem(position).getTotalValue()));
}
@NonNull
@Override
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
LayoutInflater layoutInflater = LayoutInflater.from(parent.getContext());
View view = layoutInflater.inflate(R.layout.layout_os_item, parent, false);
return new FirestoreAdapter.ViewHolder(view);
}
public class ViewHolder extends RecyclerView.ViewHolder {
private TextView osIdItem;
private TextView osClientItem;
private TextView osDateItem;
private TextView osValueItem;
public ViewHolder(View itemView) {
super(itemView);
osIdItem = itemView.findViewById(R.id.osIDItem);
osClientItem = itemView.findViewById(R.id.osClientNameItem);
osDateItem = itemView.findViewById(R.id.osDateItem);
osValueItem = itemView.findViewById(R.id.osValueItem);
}
}
}
Here is my Logcat
2022-09-09 09:58:38.479 1147-1147/com.leonardomaito.autocommobile E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.leonardomaito.autocommobile, PID: 1147
java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String com.leonardomaito.autocommobile.models.Client.getName()' on a null object reference
at com.leonardomaito.autocommobile.adapters.FirestoreAdapter.onBindViewHolder(FirestoreAdapter.java:27)
at com.leonardomaito.autocommobile.adapters.FirestoreAdapter.onBindViewHolder(FirestoreAdapter.java:18)
at com.firebase.ui.firestore.FirestoreRecyclerAdapter.onBindViewHolder(FirestoreRecyclerAdapter.java:157)
at androidx.recyclerview.widget.RecyclerView$Adapter.onBindViewHolder(RecyclerView.java:7254)
at androidx.recyclerview.widget.RecyclerView$Adapter.bindViewHolder(RecyclerView.java:7337)
at androidx.recyclerview.widget.RecyclerView$Recycler.tryBindViewHolderByDeadline(RecyclerView.java:6194)
at androidx.recyclerview.widget.RecyclerView$Recycler.tryGetViewHolderForPositionByDeadline(RecyclerView.java:6460)
at androidx.recyclerview.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:6300)
at androidx.recyclerview.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:6296)
at androidx.recyclerview.widget.LinearLayoutManager$LayoutState.next(LinearLayoutManager.java:2330)
at androidx.recyclerview.widget.LinearLayoutManager.layoutChunk(LinearLayoutManager.java:1631)
at androidx.recyclerview.widget.LinearLayoutManager.fill(LinearLayoutManager.java:1591)
at androidx.recyclerview.widget.LinearLayoutManager.onLayoutChildren(LinearLayoutManager.java:668)
at androidx.recyclerview.widget.RecyclerView.dispatchLayoutStep2(RecyclerView.java:4309)
at androidx.recyclerview.widget.RecyclerView.dispatchLayout(RecyclerView.java:4012)
at androidx.recyclerview.widget.RecyclerView.consumePendingUpdateOperations(RecyclerView.java:2028)
at androidx.recyclerview.widget.RecyclerView$1.run(RecyclerView.java:417)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:911)
at android.view.Choreographer.doCallbacks(Choreographer.java:723)
at android.view.Choreographer.doFrame(Choreographer.java:655)
at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:897)
at android.os.Handler.handleCallback(Handler.java:789)
at android.os.Handler.dispatchMessage(Handler.java:98)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:6541)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:767)
My Client class is using a Builder design pattern, along with the default constructor as required by Firestore, and a Parcelable for transfering data through Activities, I'm only adding this since I'm not sure if it could impact how Firestore is reading my data.
So, how come I can use read and write data to the database, but I can't seem to display it? I have a Client 'name' in my database, shouldn't it be displaying that?
If it helps, my ServiceOrder class requires a Vehicle and a Client object in order to be built.
This is how my data is structured in Firestore:
Thank you.
EDIT
As requested, the Firestore Reference:
public class OsActivity extends AppCompatActivity {
private FirestoreAdapter listAdapter;
private FirebaseFirestore db = FirebaseFirestore.getInstance();
private CollectionReference osRef = db.collection("cliente");
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_os);
setupRecyclerView();
}
private void setupRecyclerView() {
RecyclerView recyclerView = findViewById(R.id.recyclerViewOs);
Query query = osRef.orderBy("ServiceOrder",
Query.Direction.ASCENDING);
FirestoreRecyclerOptions<ServiceOrder> options =
new FirestoreRecyclerOptions.Builder<ServiceOrder>()
.setQuery(query, ServiceOrder.class)
.build();
listAdapter = new FirestoreAdapter(options);
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
recyclerView.setAdapter(listAdapter);
}
@Override
protected void onStart() {
super.onStart();
listAdapter.startListening();
}
@Override
protected void onStop() {
super.onStop();
listAdapter.stopListening();
}
Ran another debugger and got the following message No setter/field for ServiceOrder found on class com.leonardomaito.autocommobile.models.ServiceOrder
Database Schema
ServiceOrder Class
public class ServiceOrder {
public Client client;
public Vehicle vehicle;
private String service;
private String observation;
private String paymentForm;
private String date;
private double totalValue;
private int id;
public ServiceOrder() {
}
private ServiceOrder(ServiceOrderBuilder serviceOrderBuilder){
this.client = serviceOrderBuilder.client;
this.vehicle = serviceOrderBuilder.vehicle;
this.service = serviceOrderBuilder.service;
this.paymentForm = serviceOrderBuilder.paymentForm;
this.observation = serviceOrderBuilder.observation;
this.totalValue = serviceOrderBuilder.value;
this.date = serviceOrderBuilder.date;
}
public String getDate() {
return date;
}
public void setDate(String date) {
this.date = date;
}
public double getTotalValue() {
return totalValue;
}
public void setTotalValue(double totalValue) {
this.totalValue = totalValue;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public Client getClient() {
return client;
}
public void setClient(Client client) {
this.client = client;
}
public Vehicle getVehicle() {
return vehicle;
}
public void setVehicle(Vehicle vehicle) {
this.vehicle = vehicle;
}
public String getService() {
return service;
}
public void setService(String service) {
this.service = service;
}
public String getObservation() {
return observation;
}
public void setObservation(String observation) {
this.observation = observation;
}
public String getPaymentForm() {
return paymentForm;
}
public void setPaymentForm(String paymentForm) {
this.paymentForm = paymentForm;
}
public static class ServiceOrderBuilder {
private Vehicle vehicle;
private Client client;
private final String service;
private final String paymentForm;
private final int id;
private final double value;
private final String date;
private String observation;
public ServiceOrderBuilder(Client client, Vehicle vehicle,
String service, String paymentForm,
int id, double value, String date) {
this.client = client;
this.vehicle = vehicle;
this.service = service;
this.paymentForm = paymentForm;
this.id = id;
this.value = value;
this.date = date;
}
public ServiceOrder.ServiceOrderBuilder observation(String observation) {
this.observation = observation;
return this;
}
public ServiceOrder build() {
ServiceOrder serviceOrder = new ServiceOrder(this);
return serviceOrder;
}
}
}