在处理 firebase 数据库和 searchview 时出现致命异常

Getting a fatal exception while working on firebase database and searchview

我正在尝试将 Searchview 与 Recylerview 和 firebase 数据库一起使用,我一直在关注一些教程并且我已经正确地观看了视频所以我不知道为什么我会收到错误,我有三个 classn 一个是适配器,一个是辅助器,一个是主要的,我得到的错误是:

2021-05-12 03:16:12.931 31658-31658/com.example.search E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.example.search, PID: 31658
    com.google.firebase.database.DatabaseException: Can't convert object of type java.lang.String to type com.example.search.Deal

在以下行中:

list.add(ds.getValue(Deal.class));

这是我的主activity:

package com.example.search;

import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.SearchView;
import androidx.recyclerview.widget.RecyclerView;

import android.os.Bundle;

import android.widget.Toast;

import com.google.firebase.database.DataSnapshot;
import com.google.firebase.database.DatabaseError;
import com.google.firebase.database.DatabaseReference;
import com.google.firebase.database.FirebaseDatabase;
import com.google.firebase.database.ValueEventListener;

import java.util.ArrayList;

public class MainActivity extends AppCompatActivity {

    DatabaseReference ref;
    ArrayList<Deal> list;
    RecyclerView recyclerView;
    SearchView searchView;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        ref = FirebaseDatabase.getInstance().getReference().child("medicines");
        recyclerView = findViewById(R.id.rv);
        searchView = findViewById(R.id.searchview);

    }

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

        if(ref != null){
            ref.addValueEventListener(new ValueEventListener() {
                @NonNull
                @Override
                protected Object clone() throws CloneNotSupportedException {
                    return super.clone();
                }

                @Override
                public void onDataChange(@NonNull DataSnapshot snapshot) {
                    if(snapshot.exists()){
                        list = new ArrayList<>();
                        for(DataSnapshot ds : snapshot.getChildren()){
                            list.add(ds.getValue(Deal.class));
                        }
                        AdapterClass adapterClass = new AdapterClass(list);
                        recyclerView.setAdapter(adapterClass);

                    }
                }

                @Override
                public void onCancelled(@NonNull DatabaseError error) {
                    Toast.makeText(MainActivity.this, error.getMessage(), Toast.LENGTH_SHORT).show();
                }
            });
        }
        if (searchView != null){
            searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
                @Override
                public boolean onQueryTextSubmit(String query) {
                    return false;
                }

                @Override
                public boolean onQueryTextChange(String newText) {
                    search(newText);
                    return true;
                }
            });
        }

    }

    private void search(String str) {
        if (!str.equals("")){
            ArrayList<Deal>myList = new ArrayList<>();
            for (Deal object : list){
                if(object.getDisease().toLowerCase().contains(str.toLowerCase())){
                    myList.add(object);
                }
            }
            AdapterClass adapterClass = new AdapterClass(myList);
            recyclerView.setAdapter(adapterClass);
        }

    }

}

这是我的“帮手”class,我称之为交易:

package com.example.search;

public class Deal {
    private String disease, medication;

    public Deal() {
    }

    public Deal(String disease, String medication) {
        this.disease = disease;
        this.medication = medication;
    }

    public String getDisease() {
        return disease;
    }

    public void setDisease(String disease) {
        this.disease = disease;
    }

    public String getMedication() {
        return medication;
    }

    public void setMedication(String medication) {
        this.medication = medication;
    }
}

这是我的适配器class:

package com.example.search;

import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;

import java.util.ArrayList;

public class AdapterClass extends RecyclerView.Adapter<AdapterClass.MyViewHolder> {

    ArrayList<Deal> list;
    public AdapterClass(ArrayList<Deal> list){
        this.list = list;
    }
    @NonNull
    @Override
    public MyViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.card_holder, parent, false);
        return new MyViewHolder(view);
    }

    @Override
    public void onBindViewHolder(@NonNull MyViewHolder holder, int position) {
        holder.disease.setText(list.get(position).getDisease());
        holder.medicine.setText(list.get(position).getMedication());
    }

    @Override
    public int getItemCount() {
        return list.size();
    }

    class MyViewHolder extends RecyclerView.ViewHolder{
        TextView disease, medicine;
        public MyViewHolder(@NonNull View itemView) {
            super(itemView);
            disease = itemView.findViewById(R.id.disease);
            medicine =  itemView.findViewById(R.id.medication);
        }
    }

}

这是我的主要 activity 布局:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity"
    android:orientation="vertical">

    <androidx.appcompat.widget.SearchView
        android:id="@+id/searchview"
        android:layout_width="match_parent"
        android:layout_height="?attr/actionBarSize"
        android:padding="10dp"
        android:layout_margin="5dp"
        />

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/rv"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_margin="5dp"
        android:autofillHints="Search here"
        app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
        />
</LinearLayout>

和我的卡片视图布局

<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_margin="5dp"
    app:cardElevation="5dp">


    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        >

        <TextView
            android:id="@+id/disease"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:textSize="25sp"
            android:textStyle="bold"
            android:padding="10dp"
            android:text="disease_name" />

        <TextView
            android:id="@+id/medication"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="solution"
            android:padding="10dp"
            />
    </LinearLayout>
    <View
        android:layout_width="match_parent"
        android:layout_height="1dp"
        android:background="#000"
        />
</androidx.cardview.widget.CardView>

这就是整个应用程序的全部内容,所以我不明白为什么应用程序一直崩溃,这就是我的 firebase 数据库的样子

{
  "medicines" : {
    "disease" : "maleria",
    "medication" : "aspirin"
  }
}

我之前遇到过不同的异常,我更改了数据库中的规则并调试了应用程序,现在我发现这个错误已经持续了两个小时,老实说,我没有任何线索,我已经尝试过检查我是否写错了,如果我在 helper(deal)class 中添加的名称与 firebase 等中的名称匹配,他们这样做我不知道

由于您的 Deal class 定义了属性 diseasemediation,因此 medicines 下似乎只有一个 Deal 对象。

因此,对于您当前的数据,您不应该在 onDataChange 中对 getChildren 使用循环,只需执行以下操作:

public void onDataChange(@NonNull DataSnapshot snapshot) {
    if(snapshot.exists()){
        list = new ArrayList<>();
        list.add(snapshot.getValue(Deal.class));
        AdapterClass adapterClass = new AdapterClass(list);
        recyclerView.setAdapter(adapterClass);
    }
}