[英]Why does data from Firestore DB returns as 'null' in FirestoreRecyclerAdapter?
在從 Firestore 寫入和讀取數據成功后,我現在嘗試使用 FirestoreRecyclerAdapter 在RecyclerView
中顯示該數據。 但是,在我的onBindViewHolder
中,我嘗試使用數據庫中的數據設置 textView,我得到了 NullPointerException,其中我的客戶端名稱是 null。
這是我的 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);
}
}
}
這是我的 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)
我的Client
class 正在使用 Builder 設計模式,以及 Firestore 所需的默認構造函數,以及用於通過活動傳輸數據的 Parcelable,我只是添加它,因為我不確定它是否會影響 Firestore 讀取我的方式數據。
那么,為什么我可以使用讀寫數據到數據庫,但我似乎無法顯示呢? 我的數據庫中有一個Client
“名稱”,它不應該顯示嗎?
如果有幫助,我的ServiceOrder
class 需要Vehicle
和Client
object 才能構建。
這就是我的數據在 Firestore 中的結構方式:
謝謝你。
編輯
根據要求,Firestore 參考:
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();
}
運行另一個調試器並收到以下消息No setter/field for ServiceOrder found on class com.leonardomaito.autocommobile.models.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;
}
}
}
由於您使用的是 Firebase-UI 庫,因此當您使用以下方法調用時:
.setQuery(query, ServiceOrder.class)
這意味着您正在嘗試將查詢返回的所有文檔 map 轉換為ServiceOrder
類型的對象。 但這實際上是不可能的,因為您的實際文檔如下所示:
clienteTeste (document)
|
--- ServiceOrder (map)
|
--- client: {...} (map)
|
--- date: "09/09/2022"
|
--- //other fields
而不是這個:
clienteTeste (document)
|
--- client: {...} (map)
|
--- date: "09/09/2022"
|
--- //other fields
看,沒有ServiceOrder
額外的object? 這將是解決此問題的最簡單解決方案,其中字段應直接添加到文檔中,而不是map 內。
但是,如果您無法更改文檔結構,我對此表示懷疑,因為那里只有一個(測試)文檔,那么您應該考慮通過創建另一個 class 來使用封裝,其中包含一個名為ServiceOrder
的單個字段,該字段的類型應該是ServiceOrder
。 然后將map的每一個文件變成一個object這個新的class。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.