简体   繁体   English

为什么 Firestore 数据库中的数据在 FirestoreRecyclerAdapter 中返回为“null”?

[英]Why does data from Firestore DB returns as 'null' in FirestoreRecyclerAdapter?

After being successful with writing and reading data from Firestore, I am now trying to display that data in a RecyclerView by utilizing FirestoreRecyclerAdapter.在从 Firestore 写入和读取数据成功后,我现在尝试使用 FirestoreRecyclerAdapter 在RecyclerView中显示该数据。 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.但是,在我的onBindViewHolder中,我尝试使用数据库中的数据设置 textView,我得到了 NullPointerException,其中我的客户端名称是 null。

Here is my FirestoreAdapter class:这是我的 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这是我的 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.我的Client class 正在使用 Builder 设计模式,以及 Firestore 所需的默认构造函数,以及用于通过活动传输数据的 Parcelable,我只是添加它,因为我不确定它是否会影响 Firestore 读取我的方式数据。

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?我的数据库中有一个Client “名称”,它不应该显示吗?

If it helps, my ServiceOrder class requires a Vehicle and a Client object in order to be built.如果有帮助,我的ServiceOrder class 需要VehicleClient object 才能构建。

This is how my data is structured in Firestore:这就是我的数据在 Firestore 中的结构方式:

Part1第1部分

Part2第2部分

Thank you.谢谢你。

EDIT编辑

As requested, the Firestore Reference:根据要求,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();
    }

Ran another debugger and got the following message No setter/field for ServiceOrder found on class com.leonardomaito.autocommobile.models.ServiceOrder运行另一个调试器并收到以下消息No setter/field for ServiceOrder found on class com.leonardomaito.autocommobile.models.ServiceOrder

Database Schema数据库模式

Firebase Console Firebase 控制台

ServiceOrder Class服务订单 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;

        }
    }
}



Since you're using the Firebase-UI library, when you're using the following method call:由于您使用的是 Firebase-UI 库,因此当您使用以下方法调用时:

.setQuery(query, ServiceOrder.class)

It means that you're trying to map all documents that are returned by the query into objects of type ServiceOrder .这意味着您正在尝试将查询返回的所有文档 map 转换为ServiceOrder类型的对象。 But this is actually not possible because your actual document looks like this:但这实际上是不可能的,因为您的实际文档如下所示:

clienteTeste (document)
  |
  --- ServiceOrder (map)
        |
        --- client: {...} (map)
        |
        --- date: "09/09/2022"
        |
        --- //other fields

Instead of this:而不是这个:

clienteTeste (document)
  |
  --- client: {...} (map)
  |
  --- date: "09/09/2022"
  |
  --- //other fields

See, there is no ServiceOrder extra object?看,没有ServiceOrder额外的object? This would be the simplest solution for solving this issue, in which the fields should be added directly into the document not inside a map.这将是解决此问题的最简单解决方案,其中字段应直接添加到文档中,而不是map 内。

If you however cannot change the document structure, which I doubt, since there is only one (test) document present there, then you should consider using encapsulation by creating another class with a single field called ServiceOrder which should be of type ServiceOrder .但是,如果您无法更改文档结构,我对此表示怀疑,因为那里只有一个(测试)文档,那么您应该考虑通过创建另一个 class 来使用封装,其中包含一个名为ServiceOrder的单个字段,该字段的类型应该是ServiceOrder And then map each document into an object of this new class.然后将map的每一个文件变成一个object这个新的class。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 无法在 Firestore 中找到文档数据,返回 null - Cant find document data in Firestore, returns null Flutter 当firestore中有数据时,firestore返回长度0 - Flutter firestore returns length 0 while there is data in firestore 从 Firestore 中提取数据时,Flatlist 不呈现 - Flatlist does not render when pulling data from firestore 从 Firebase 加载数据仅在第一次返回 null - loading data from Firebase returns null only for the first time 即使有数据js,firestore也会得到null - firestore getting null even if there is data js Flutter 错误 - 断言失败:第 213 行 pos 15:'data:= null':在从 firestore 获取数据时不正确 - Flutter error - failed assertion: line 213 pos 15: 'data != null': is not true at the time of fetching data from firestore Function 从 flutter 中的 firestore 返回一个值 - Function that returns a value from firestore in flutter Stream 构建器在使用 Firestore 发布的 flutter 应用程序上返回 null - Stream builder returns null on released flutter app using firestore 为什么从 Firestore 读取不存在的文档会返回未捕获的 promise? - Why does reading a non existing document from firestore return in a uncaught promise? 使用来自 firestore 的数据初始化 useState - initialize useState with data from firestore
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM