首页 > 解决方案 > 在 Android Kotlin 聊天应用程序中显示聊天列表时出现数据库异常

问题描述

我一直在使用 Kotlin 和 Firebase 在 Android 中开发一个聊天应用程序。注册,搜索和发送消息给用户,这一切都成功了。但我无法生成一个聊天列表,它是用户最近聊天的列表。用户可以点击它来访问特定的聊天,就像任何其他聊天应用程序一样。

用户存储在用户模型中,数据以相同的格式注册到数据库中。

我可以使用 addValueEventListener 方法显示用户的个人资料图片,但是当为聊天列表调用类似方法时,它会引发错误 - com.google.firebase.database.DatabaseException:无法转换 java 类型的对象。 lang.String 类型 kushwaha.samir.boop.models.User

这是发生错误的代码 -

val user = snapshot.getValue<User>(User::class.java!!)

存在于函数中 - chatList()

数据库视图

MainActivityChat 代码 >

class MainActivityChat : Fragment() {
    lateinit var profile_image: CircleImageView

    lateinit var firebaseUser: FirebaseUser
    lateinit var reference: DatabaseReference
    lateinit var referenceusers: DatabaseReference
    lateinit var referenceuserschats: DatabaseReference
    lateinit var referencechatlist: DatabaseReference


    var root: View? = null
    lateinit var auth: FirebaseAuth

    lateinit var fragment: Fragment

    var recyclerView: RecyclerView? = null

    var userAdapter: UserAdapter? = null
    var mUsers: MutableList<User>? = null

    var fuser: FirebaseUser?=null

    private var usersList: MutableList<Chatlist>? = null

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
        root = inflater.inflate(R.layout.activity_mainchat, container, false)
        setHasOptionsMenu(true)

        firebaseUser = FirebaseAuth.getInstance().currentUser!!

        val uid = firebaseUser.uid

        val floatingActionButton = root!!.findViewById(R.id.searchPerson) as FloatingActionButton

        floatingActionButton.setOnClickListener {
            val intent = Intent(activity, SearchActivity::class.java)
            startActivity(intent)
        }

        fuser = FirebaseAuth.getInstance().currentUser!!

        usersList = ArrayList()



        reference = FirebaseDatabase.getInstance().getReference("Chatlist").child(fuser!!.uid)
        referencechatlist = FirebaseDatabase.getInstance().getReference("Chatlist").child(fuser!!.uid)


        profile_image = root!!.findViewById(R.id.profile_image)


        firebaseUser = FirebaseAuth.getInstance().currentUser!!
        FirebaseDatabase.getInstance().reference.child("Users").child(uid)
            .addValueEventListener(object : ValueEventListener {

                override fun onDataChange(dataSnapshot: DataSnapshot) {
                    val user = dataSnapshot.getValue(User::class.java)
                    //   usernamedisplay.text = user!!.username
                    if (user!!.profileImageUrl == "default") {
                        profile_image.setImageResource(R.mipmap.ic_launcher)
                        Log.d(ProfileFragment.TAG, "No image retrieved/found")
                    } else {
                        //change this
                        context?.let { Glide.with(it).load(user.profileImageUrl).into(profile_image) }!!
                        Log.d(ProfileFragment.TAG, "Image set")
                    }
                }

                override fun onCancelled(databaseError: DatabaseError) {

                }
            })

        reference = FirebaseDatabase.getInstance().getReference("Chats")
        reference.addValueEventListener(object : ValueEventListener {
            override fun onCancelled(p0: DatabaseError) {
                TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
            }

            override fun onDataChange(dataSnapshot: DataSnapshot) {
                var unread = 0
                for (snapshot in dataSnapshot.children) {
                    val chat = snapshot.getValue<Chat>(Chat::class.java!!)
                    if (chat!!.receiver == firebaseUser!!.uid && !chat!!.isIsseen!!) {
                        unread++
                    }
                }

                reference = FirebaseDatabase.getInstance().getReference("Chatlist").child(fuser!!.uid)
                reference.addValueEventListener(object : ValueEventListener {
                    override fun onDataChange(dataSnapshot: DataSnapshot) {
                        usersList!!.clear()
                        for (snapshot in dataSnapshot.children) {
                            val chatlist = snapshot.getValue<Chatlist>(Chatlist::class.java!!)
                            usersList!!.add(chatlist!!)
                        }

                        chatList()
                    }

                    override fun onCancelled(databaseError: DatabaseError) {

                    }
                })



            }
            })

        updateToken(FirebaseInstanceId.getInstance().token)


        return root
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

        recyclerView = view!!.findViewById(R.id.recycler_viewmain)
        recyclerView!!.setHasFixedSize(true)
        recyclerView!!.layoutManager = LinearLayoutManager(context)
    }

    private fun updateToken(token: String?) {
        val reference = FirebaseDatabase.getInstance().getReference("Tokens")
        val token1 = Token(token!!)
        reference.child(fuser!!.uid).setValue(token1)
    }

    private fun chatList() {
        mUsers = ArrayList()
        reference = FirebaseDatabase.getInstance().getReference("Users")

        reference.addValueEventListener(object : ValueEventListener {
            override fun onDataChange(dataSnapshot: DataSnapshot) {
                mUsers!!.clear()
                for (snapshot in dataSnapshot.children) {
                    **val user = snapshot.getValue<User>(User::class.java!!)**
                    for (chatlist in usersList!!) {
                        if (user!!.id == chatlist.id) {
                            mUsers!!.add(user)
                        }
                    }
                }
                userAdapter = UserAdapter(context!!, mUsers!!, true)
                recyclerView!!.adapter = userAdapter
            }

            override fun onCancelled(databaseError: DatabaseError) {

            }
        })

    }


    private fun status(status: String) {
        reference = FirebaseDatabase.getInstance().getReference("Users").child(firebaseUser!!.uid)

        val hashMap = HashMap<String, Any>()
        hashMap["status"] = status

        reference.updateChildren(hashMap)
    }

    override fun onResume() {
        super.onResume()
        status("online")
    }

    override fun onPause() {
        super.onPause()
        status("offline")
    }

    companion object {
        val TAG = "MainActivityChat"
    }
}

用户模型

class User {

  var id: String? = null
  var phoneno: String? = null
  var profileImageUrl: String? = null
  var search: String? = null
  var status: String? = null
  var username: String? = null

  constructor(id: String, phoneno: String, profileImageUrl: String, search: String, status: String, username: String) {
    this.id = id
    this.phoneno = phoneno
    this.profileImageUrl = profileImageUrl
    this.search = search
    this.status = status
    this.username = username
  }

  constructor() {

  }
}

聊天列表模型

import android.os.Parcelable
import kotlinx.android.parcel.Parcelize

@Parcelize
class Chatlist(val id: String):
    Parcelable {
    constructor() : this("")
}

日志猫

2019-03-02 22:20:52.446 20562-20562/kushwaha.samir.boop E/AndroidRuntime: FATAL EXCEPTION: main
    Process: kushwaha.samir.boop, PID: 20562
    com.google.firebase.database.DatabaseException: Can't convert object of type java.lang.String to type kushwaha.samir.boop.models.User
        at com.google.firebase.database.core.utilities.encoding.CustomClassMapper.convertBean(com.google.firebase:firebase-database@@16.0.5:423)
        at com.google.firebase.database.core.utilities.encoding.CustomClassMapper.deserializeToClass(com.google.firebase:firebase-database@@16.0.5:214)
        at com.google.firebase.database.core.utilities.encoding.CustomClassMapper.convertToCustomClass(com.google.firebase:firebase-database@@16.0.5:79)
        at com.google.firebase.database.DataSnapshot.getValue(com.google.firebase:firebase-database@@16.0.5:212)
        at kushwaha.samir.boop.MainActivityChat$chatList$1.onDataChange(MainActivityChat.kt:187)
        at com.google.firebase.database.core.ValueEventRegistration.fireEvent(com.google.firebase:firebase-database@@16.0.5:75)
        at com.google.firebase.database.core.view.DataEvent.fire(com.google.firebase:firebase-database@@16.0.5:63)
        at com.google.firebase.database.core.view.EventRaiser$1.run(com.google.firebase:firebase-database@@16.0.5:55)
        at android.os.Handler.handleCallback(Handler.java:873)
        at android.os.Handler.dispatchMessage(Handler.java:99)
        at android.os.Looper.loop(Looper.java:193)
        at android.app.ActivityThread.main(ActivityThread.java:6762)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)

标签: androidfirebasefirebase-realtime-databasekotlin

解决方案


根据您的评论,您说当您尝试记录snapshot对象的内容时,您会得到:

{ key = status, value = offline } 

这显然意味着您使用了错误的参考。所以你得到这个结果是因为你在数据库中获得了statusString 类型的属性的引用,这就是你得到那个错误的原因:

com.google.firebase.database.DatabaseException:无法将 java.lang.String 类型的对象转换为 kushwaha.samir.boop.models.User 类型

要解决此问题,请更改以下代码行:

reference.addValueEventListener(object : ValueEventListener {}

val rootRef = FirebaseDatabase.getInstance().getReference()
val usersRef = rootRef.child("Users")
usersRef.addValueEventListener(object : ValueEventListener {}

推荐阅读