Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Kotlin No setter/field for Value found on class Object warning for Firebase

I'm trying to fetch all messages data inside my ChatMessage data class from my Firebase Database. In the logs, I can see that data is indeed fetched inside my Snapshot, but it isn't getting assigned to my variables in the data class. I'm new to Kotlin & Firebase, so I don't really understand why is it happening?

After I did some logs searching I found out that I have been receiving this warning:

W/ClassMapper: No setter/field for -Llk34LtqGPJ3bwPrYRi found on class com.idiotboxes.socialowl.models.ChatMessage

Did some searching for this error here & found it is a very common problem indeed. But my issue, none of the solutions have a data class format like mine.

I understand that the warning is saying I need to setup getters & setters in my data class, but I'm fairly new to Kotlin & I don't know how to implement getter-setters in my data class.

Here's how my data class ChatMessage looks like:

package com.idiotboxes.socialowl.models

data class ChatMessage(val messageID: String, val fromID: String, val toID: 
String,val message: String, val timeStamp: Long){

    //No argument constructor
    constructor(): this("","","","",-1)
}

Here is how my Firebase Database node looks like: Database Structure

EDIT: Here's extra code to help you understand where the problem could be

My Callback interface

interface FirebaseCallback {

    fun onCallback(latestMessage: ChatMessage)

}

My function which reads the Data from Firebase

private fun readFirebaseData(firebaseCallback: FirebaseCallback){
    //Signed In user's ID
    val fromID = FirebaseAuth.getInstance().uid
    Log.w(TAG, "from ID is: $fromID (Currently Signed-In user)")

    //Get Database Reference
    val msgRef = FirebaseDatabase.getInstance().getReference("/Latest-messages/$fromID"/* Reference to current user's database entry */)

    //Set a Listener for new messages
    msgRef.addChildEventListener(object: ChildEventListener {
        //adds new row when someone messages you for the first time, i.e. New Child is Added
        override fun onChildAdded(p0: DataSnapshot, p1: String?) {
            Log.w(TAG, "Snapshot captured from Firebase Database is: $p0")
            //Convert snapshot to messages
            //val latestMessage = p0.getValue(ChatMessage::class.java) ?: return
            val callbackData: ChatMessage = p0.getValue(ChatMessage::class.java) ?: return
            //TODO Implement Callback
            firebaseCallback.onCallback(callbackData)
        }

        //Updates existing rows latest messages when user receives new message i.e. Latest Message child is Changed.
        override fun onChildChanged(p0: DataSnapshot, p1: String?) {
            val latestMessage: ChatMessage = p0.getValue(ChatMessage::class.java) ?: return//If Null then return

            //Update the Existing row with new message
            latestMessagesHashMap[p0.key!!] = latestMessage
            updateRecyclerView()

        }
    --Some redundant methods of ChildEventListener--
    })
    latest_messages_recycler_view.adapter = adapter
    //Recycler View Bottom Line Border
    latest_messages_recycler_view.addItemDecoration(DividerItemDecoration(activity, DividerItemDecoration.VERTICAL))
}

Function where I attempt to retrieve data from my callback

private fun showLatestMessages(){

readFirebaseData(object : FirebaseCallback{
        override fun onCallback(latestMessage: ChatMessage) {
            //TODO latestMessage is  not null. But blank values are  being filled  in the Chat Message model class
            Log.w(TAG, "NotNull latestMessage values are fromID: ${latestMessage.fromID} toID: ${latestMessage.toID} Typed Message: ${latestMessage.message} TimeStamp: ${latestMessage.timeStamp}")

            //Add the new message row
            adapter.add(LatestMessagesItems(latestMessage, context ?: return))
        }
    })

    //Set OnClick Listener on Recycler View Items
    adapter.setOnItemClickListener { item, view ->
        //Grab the User details from the item that is clicked.
        val userItem = item as LatestMessagesItems

        //Start Chat Activity with the clicked User
        val startChat = Intent(activity, ChatActivity::class.java)
        startChat.putExtra(USER_KEY, userItem.recipientUser)
        startActivity(startChat)
    }
}

private fun updateRecyclerView(){
    //Clear existing rows
    adapter.clear()
    //Fetch all Latest Messages from HashMap
    latestMessagesHashMap.values.forEach {
        adapter.add(LatestMessagesItems(it, context?: return))
    }
}

My messages item for my recyclerview

class LatestMessagesItems(val latestMessage: ChatMessage, val ctx: Context): Item<ViewHolder>(){

lateinit var recipientUser: User

override fun getLayout(): Int {
    return R.layout.latest_message_row
}

override fun bind(viewHolder: ViewHolder, position: Int) {

    Log.w(TAG, "Fetched latest Message is: $latestMessage")
    //Null Check
    val recipientID: String? = if (latestMessage.fromID == FirebaseAuth.getInstance().uid) {
        latestMessage.toID
    } else {
        latestMessage.fromID
    }

    //Fetch the recipient user details
    val fetchRef = FirebaseDatabase.getInstance().getReference("/users/$recipientID")
    fetchRef.addListenerForSingleValueEvent(object: ValueEventListener{
        override fun onDataChange(p0: DataSnapshot) {
            Log.w(TAG, "Fetched Recipient ID is: $recipientID")
            //Fetch user details in User model class
            recipientUser = p0.getValue(User::class.java) ?: return
            Log.w(TAG, "Fetched Recipient User Name is: ${recipientUser.username}")

            //Fill the User Details
            viewHolder.itemView.recipient_username.text = recipientUser.username //Username
            Glide.with(ctx).load(recipientUser.profileImage).into(viewHolder.itemView.recipient_profile_image) //Profile Pic
        }

            override fun onCancelled(p0: DatabaseError) {

            }
        })

        //Latest Message Received
        viewHolder.itemView.latest_received_message.text = latestMessage.message
    }
}

And Finally I updated my Model Class according to some of the suggestions posted here. ChatMessage.kt

package com.idiotboxes.socialowl.models

data class ChatMessage(var messageID: String? = null, var fromID: String? = null , var toID: String? = null ,var message: String? = null , var timeStamp: Long? = null){
    //No argument constructor
    constructor(): this("","","","",-1)
}

Yet, the problem still persists.

like image 874
Rishabh More Avatar asked Oct 24 '25 16:10

Rishabh More


1 Answers

I can't say for sure it's the case but I think that you should write to variables (var), not values (val).

This is because Kotlin automatically generates getters/setters for var, which is considered mutable, and doesn't for val which is considered immutable.

The same happens for private vars as Kotlin doesn't provide getters/setters for them outside their local scope (e.g. for Firebase to access them).

like image 115
Panos Savvaidis Avatar answered Oct 26 '25 15:10

Panos Savvaidis