簡體   English   中英

為什么 Firestore 數據庫中的數據在 FirestoreRecyclerAdapter 中返回為“null”?

[英]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 需要VehicleClient object 才能構建。

這就是我的數據在 Firestore 中的結構方式:

第1部分

第2部分

謝謝你。

編輯

根據要求,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

數據庫模式

Firebase 控制台

服務訂單 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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM