You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Firebase数据库类型转换异常:String转Kelas类致Kotlin应用崩溃

问题描述

运行Kotlin开发的Edumathh应用时崩溃,抛出com.google.firebase.database.DatabaseException异常,提示无法将java.lang.String类型转换为com.edushare.edumathh.home.kelas.model.Kelas类型。

相关代码

Fragment代码

class KelasFragment : Fragment() {

    private lateinit var preferences: Preferences
    private lateinit var mDatabase: DatabaseReference
    private var datalist = ArrayList<Kelas>()
    private var _binding : FragmentKelasBinding? = null

    private val binding get() = _binding!!

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        _binding = FragmentKelasBinding.inflate(inflater, container, false  )
        return binding.root
    }

    override fun onActivityCreated(savedInstanceState: Bundle?) {
        super.onActivityCreated(savedInstanceState)

        preferences = Preferences(requireActivity().applicationContext)
        mDatabase = FirebaseDatabase.getInstance().getReference("Kelas")

        binding.tvName.text = preferences.getValues("nama")
        binding.tvSchool.text = preferences.getValues("sekolah")
        Glide.with(this)
            .load(preferences.getValues("url"))
            .apply(RequestOptions.circleCropTransform())
            .into(binding.ivAvatar)

        binding.rvKelas.layoutManager = LinearLayoutManager(context)
        getData()

    }

    private fun getData() {
        mDatabase.addValueEventListener(object : ValueEventListener{
            override fun onDataChange(snapshot: DataSnapshot) {
                datalist.clear()
                for (getSnapshot in snapshot.children){
                    var kelas = getSnapshot.getValue(Kelas::class.java)
                    datalist.add(kelas!!)
                }
                binding.rvKelas.adapter = KelasTersediaAdapter(datalist){
                    var intent = Intent(context,DetailKelasActivity::class.java).putExtra("data",it)
                    startActivity(intent)
                }
            }

            override fun onCancelled(error: DatabaseError) {
                Toast.makeText(context, ""+ error.message, Toast.LENGTH_LONG).show()
            }

        })
}

    override fun onDestroyView() {
        super.onDestroyView()
        _binding = null
}

}

Firebase数据库结构

{
  "Istilah": {
    "Median": {
      "desc": "Nilai tengah",
      "istilah": "Median"
    },
    "Rata-rata": {
      "desc": "Rata-rata",
      "istilah": "Mean"
    }
  },
  "Kelas": {
    "desc": "Kelas XII semester II",
    "title": "Statistika"
  },
  "User": {
    "1": {
      "email": "bagicode@gmail.com",
      "nama": "Robby Dianputra",
      "password": "1",
      "saldo": "500000",
      "url": "https://yt3.ggpht.com/a/AGF-l79H3wIgvBVl0bD5No1VMvfjo_DuhdPjQXWfvw=s288-c-k-c0xffffffff-no-rj-mo",
      "username": "1"
    },
    "009": {
      "nama": "\"Rahmatul Ulya\"",
      "password": "009",
      "sekolah": "SMAN 1 Banda Aceh",
      "url": "https://firebasestorage.googleapis.com/v0/b/edumath-f7c8a.appspot.com/o/images%2F178a0569-f4f0-49e4-9f98-f4fb58a94f6d?alt=media&token=58cb5004-607f-4f0c-afa4-8b821f024b33",
      "username": "009"
    }
  }
}

LogCat日志

E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.edushare.edumathh, PID: 21519
    com.google.firebase.database.DatabaseException: Can't convert object of type java.lang.String to type com.edushare.edumathh.home.kelas.model.Kelas
        at com.google.firebase.database.core.utilities.encoding.CustomClassMapper.convertBean(CustomClassMapper.java:436)
        at com.google.firebase.database.core.utilities.encoding.CustomClassMapper.deserializeToClass(CustomClassMapper.java:232)
        at com.google.firebase.database.core.utilities.encoding.CustomClassMapper.convertToCustomClass(CustomClassMapper.java:80)
        at com.google.firebase.database.DataSnapshot.getValue(DataSnapshot.java:203)
        at com.edushare.edumathh.home.kelas.KelasFragment$getData$1.onDataChange(KelasFragment.kt:59)
        at com.google.firebase.database.core.ValueEventRegistration.fireEvent(ValueEventRegistration.java:75)
        at com.google.firebase.database.core.view.DataEvent.fire(DataEvent.java:63)
        at com.google.firebase.database.core.view.EventRaiser$1.run(EventRaiser.java:55)
        at android.os.Handler.handleCallback(Handler.java:739)
        at android.os.Handler.dispatchMessage(Handler.java:95)
        at android.os.Looper.loop(Looper.java:135)
        at android.app.ActivityThread.main(ActivityThread.java:5254)
        at java.lang.reflect.Method.invoke(Native Method)
        at java.lang.reflect.Method.invoke(Method.java:372)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:903)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:698)
I/Process: Sending signal. PID: 21519 SIG: 9
解决方案

问题根源在于数据库结构和代码逻辑不匹配:Kelas节点直接存储了单个Kelas对象的属性(desc和title),但代码里却遍历snapshot.children,把每个子节点(也就是desc和title这两个字符串值)尝试转换成Kelas对象,自然会触发类型转换失败。

提供两种修复方式:

方式一:调整数据库结构(推荐,支持多班级数据)

修改Kelas节点为包含多个子节点的列表结构,每个子节点是独立的Kelas对象,示例如下:

"Kelas": {
  "kelas1": {
    "desc": "Kelas XII semester II",
    "title": "Statistika"
  },
  "kelas2": {
    "desc": "Kelas XI semester I",
    "title": "Aljabar"
  }
}

调整后代码中的遍历逻辑可正常工作,每个getSnapshot对应一个完整的Kelas对象。

方式二:调整代码逻辑(适配当前单班级数据库结构)

如果暂时只需要单个班级数据,直接读取Kelas节点的数据,无需遍历子节点,修改后的getData函数如下:

private fun getData() {
    mDatabase.addValueEventListener(object : ValueEventListener{
        override fun onDataChange(snapshot: DataSnapshot) {
            datalist.clear()
            // 直接读取当前节点的Kelas对象
            val kelas = snapshot.getValue(Kelas::class.java)
            kelas?.let { datalist.add(it) }
            binding.rvKelas.adapter = KelasTersediaAdapter(datalist){
                val intent = Intent(context,DetailKelasActivity::class.java).putExtra("data",it)
                startActivity(intent)
            }
        }

        override fun onCancelled(error: DatabaseError) {
            Toast.makeText(context, error.message, Toast.LENGTH_LONG).show()
        }
    })
}

额外注意:需确保Kelas数据类的属性名称与数据库键完全一致(desc、title),且包含空参构造函数,示例如下:

data class Kelas(
    val desc: String? = null,
    val title: String? = null
)

内容的提问来源于stack exchange,提问作者Rahmatul Ulya

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.30 03:27:05