Class is missing a constructor with no arguments -

2019-01-29 11:07发布

问题:

I am trying to retrieve the user's info after they log in from Firebase. I have the sneaking suspicion that this error isn't actually my problem - and has to deal with the fact that I'm using ServerValue.Timestamp to store the date/time for a user when they've registered (as I'm trying to pull dateJoined back out, and my class has no idea what to do with it). My database looks something like this:

And when logging in, this is the code I use to grab the user's information

//grab user's name from firebase
//drill down to specific user
val usersRef = FirebaseDatabase.getInstance().getReference("Users")
val loggedInUserRef = usersRef.child(user.uid) //specific to the logged in user
val dataRef = loggedInUserRef.child("UserInfo") //get logged in user info
//attach listener
dataRef.addListenerForSingleValueEvent(object : ValueEventListener {
    override fun onDataChange(dataSnapshot: DataSnapshot) {
        // Get Post object and use the values to update the UI
        val user_data = dataSnapshot.getValue(User::class.java)
        Log.w(TAG, dataSnapshot.value.toString())

        //add relevant data to shared preferences
        prefs.userName = "$user_data.FirstName $user_data.LastName"
    }

    override fun onCancelled(databaseError: DatabaseError) {}
})

And I have my User class in a separate file here:

package androidproject.project_rc

    data class User(
            var FirstName: String = "",
            var LastName: String = "",
            var Email: String = "",
            var Password: String = "",
            var DateJoined: Any
    )

Around this line: val user_data = dataSnapshot.getValue(User::class.java) is where the error gets thrown - what gives?

回答1:

Have a look at the Docs Here

When using the snap.getValue(Class) getter, the class should have a 0 argument constructor.

So unfortunatly you can't use a data class for that way. Just rewrite your class as

class User(){
    var firstName: String = ""
    var lastName: String = ""
    var email: String = ""
    var password: String = ""
    var dateJoined: Long = 0L
}

You might want to use lower case variable names, as it is convention. Also, you can avoid Any for dateJoined, as I assume it is a UTC timestamp.

The firebase sdk will then check for each of the database keys if a setter/public field for that name exists and if so, set it. Kotlin generates setters and getters automaticly, so you only have to make sure that the members are named the same as the keys in your database.

Even though one of the developers once said (and this seems to not appear in the docs) that the sdk will try to access multiple nameing styles. This is quite vague, so better make sure to match the database keys.



回答2:

Not sure about Kotlin(never used it) but i think the pojo field names have to match the Firebase entry name

like:

var Password: String = "",

has the capital "P" but in your Firebase the "Password" is spelled with a lower case..



回答3:

If all primary constructor parameters have default values, Kotlin will generate a parameterless constructor as well. In your case DateJoined is missing one. So

data class User(
        var FirstName: String = "",
        var LastName: String = "",
        var Email: String = "",
        var Password: String = "",
        var DateJoined: ... = ...
)

(I don't know which types are allowed for fields in FireBase, but Any probably isn't one and if it is it can't be efficient.)