Running into an error I have been researching and attempting to fix for the past couple weeks. There are tons of suggestions out there and I've tried at least half a dozen with the same result each time.
How does Kotlin access Firebase data and populate a very simple data class?
Error: com.google.firebase.database.DatabaseException:
Can't convert object of type java.lang.String to type com.touchtapapp.handsofhope.LandingTextTitles
Read about suggestions to first convert to a Map and then to my custom data class... attempted this, successfully created the Mapped values w/ correct data... but ran into the exact same error when sending the Mapped values to the customs data class (LandingTextTitles).
Current code:
Data Model Class
data class LandingTextTitles(
val subTitle: String,
val title: String
)
Method to retrieve data from firebase
private fun initTitles() {
val ref = FirebaseDatabase.getInstance().getReference("/landing")
ref.addListenerForSingleValueEvent(object: ValueEventListener {
override fun onDataChange(p0: DataSnapshot) {
p0.children.forEach {
val titles = it.getValue(LandingTextTitles::class.java)
}
}
override fun onCancelled(p0: DatabaseError) {
// Handle Cancelled Data
}
})
// Log the titles value to see if data passed correctly
Log.d("Titles", titles.toString())
}
When I log out something like Log.d(it.toString()), I see the keys and values just fine. What am I doing wrong here?
EDIT:
Firebase data snapshot
EDIT 2:
If we use Log.d("Titles", it.toString()), we get the following:
D/Titles: DataSnapshot { key = subTitle, value = Start Here. }
D/Titles: DataSnapshot { key = title, value = Facing unexpected problems? }
If you have the following database:
landing
randomId
subTitle : "Awesome"
title : "Developer Team"
Then you can retrieve title and subTitle by doing the following:
private fun initTitles() {
val ref = FirebaseDatabase.getInstance().getReference("/landing")
ref.addListenerForSingleValueEvent(object: ValueEventListener {
override fun onDataChange(p0: DataSnapshot) {
p0.children.forEach {
val title = it.child("title").getValue(String::class.java)
val subTitle = it.child("subTitle").getValue(String::class.java)
}
}
override fun onCancelled(p0: DatabaseError) {
// Handle Cancelled Data
}
})
// Log the titles value to see if data passed correctly
Log.d("Titles", titles.toString())
}
If you want to use the data class, then change this:
override fun onDataChange(p0: DataSnapshot) {
p0.children.forEach {
val titles = it.getValue(LandingTextTitles::class.java)
}
into this:
override fun onDataChange(p0: DataSnapshot) {
val titles = p0.getValue(LandingTextTitles::class.java)
}
Related
This is what my database looks like:
Realtime Database Layout
And this is my model class:
class Registrations {
private var userEmail:String =""
private var verified:Boolean = false
constructor()
constructor(userEmail:String, verified:Boolean){
this.userEmail = userEmail
this.verified = verified
}
fun getUserEmail():String{
return userEmail
}
fun setUserEmail(userEmail: String){
this.userEmail = userEmail
}
fun getVerified():Boolean{
return verified
}
fun setVerified(verified: Boolean){
this.verified = verified
}
}
I am using a RecyclerAdapter to get the data and my code to do that is:
private fun getRegistrations() {
FirebaseDatabase.getInstance().reference.child("Registrations").addListenerForSingleValueEvent(object : ValueEventListener {
override fun onDataChange(dataSnapshot: DataSnapshot) {
if (dataSnapshot.exists()) {
itemList!!.clear()
for (snapshot in dataSnapshot.children) {
Log.d("ITEM", snapshot.toString())
val item = snapshot.getValue(Registrations::class.java)
itemList!!.add(item!!)
}
registrationsAdapter!!.notifyDataSetChanged()
}
}
override fun onCancelled(error: DatabaseError) {
TODO("Not yet implemented")
}
})
}
}
Now as you can see in the database image how do I pass the key value(email of the user) as a value to the model class?
I have tried creating an object but I am doing something wrong/don't know how to, any help is appreciated.
Also, this app is in production so I can't change the data to have email as a value in firebase now.
Any help is appreciated.
It's always recommended that the fields in the class must match the ones in the database. So if a node in the database contains two fields, verified and activationCode, then the class should contain the same.
this app is in production so I can't change the data to have email as a value in fFirebase now.
So if you cannot add the email as a value, which I doubt as it's a really simple update operation, then you can only read the key and use the setter to add in your object like this:
val item = snapshot.getValue(Registrations::class.java)
val userEmail = snapshot.getKey()
item.setUserEmail(userEmail)
itemList!!.add(item!!)
I'm new to Android & I don't know how to get all the firebase snapshot data at once inside the UID in the single data class.
val usersPrivateRef = Constants.FIREBASE_RESIDENT_PRIVATE
usersPrivateRef?.child("Fs0qczU3GsfJuGDGAeEN7bIgfjD3")
?.addListenerForSingleValueEvent(object : ValueEventListener{
override fun onDataChange(snapshot: DataSnapshot) {
if (snapshot.exists()) {
println(snapshot)
} else {
showLongToast("Snapshot not exists")
}
}
override fun onCancelled(error: DatabaseError) {}
})
To get a value from the DataSnapshot you can use its child() and getValue calls. For example, to print Krishna's email, you'd do:
println(snapshot.child("personalDetails/email").getValue(String::class.java)
I have found a solution for my above question
With the help of Gson library & also I have created the Kotlin data classes same as my snapshot data.
private var residentDATA : ArrayList<MineUserInfo> = ArrayList<MineUserInfo>()
var gson = Gson()
val json = Gson().toJson(snapshot.value)
var data = gson?.fromJson(json, MineUserInfo::class.java)
residentDATA.add(data)
I'm trying to retrieve submittedRequests from database .
userRef.addValueEventListener(object : ValueEventListener {
override fun onCancelled(p0: DatabaseError) {
}
override fun onDataChange(snapshot: DataSnapshot) {
if(snapshot!!.exists()){
val children=snapshot!!.children
for(item in children) {
val retrieveUser= item.getValue(User::class.java) //it crashes here
if (retrieveUser != null) {
userData.add(retrieveUser)
}
}
}
}
})
User Class
class User(val userId:String="", val name:String="", val surname:String="", val profileImageUrl: String="",val submittedRequests:String="", val pickedUpRequests:String="")
Error Message is :
com.google.firebase.database.DatabaseException: Failed to convert value of type java.util.HashMap to String
How can I retrieve submittedRequests from database properly?
You're declared submittedRequests:String="" in your User class. Looking at your JSON the submittedRequests is not a simple string, but rather a nested object, or a map.
This should work better
submittedRequests:Map<String, Any>=hashMapOf<String, Any>()
Can someone help me fix it?
Following code works without any error, however, it does not retrieve data from Firebase and show in the TextView.
private fun viewData() {
val postReference = FirebaseDatabase.getInstance().getReference("dataID")
val dbView= findViewById<TextView>(R.id.txtFdbData)
val postListener = object : ValueEventListener {
override fun onDataChange(dataSnapshot: DataSnapshot) {
val post = dataSnapshot.getValue(Post::class.java)
dbView.text=post?.postName
}
override fun onCancelled(databaseError: DatabaseError) {
}
}
postReference.addValueEventListener(postListener)
Toast.makeText(this,"Retrieved",Toast.LENGTH_LONG).show()
}
Above code is called when I tap the button 'btnView'
viewButton = findViewById(R.id.btnView)
viewButton.setOnClickListener {
viewData()
}
When I hit the button it shows the toast message 'Retrieved' and the default value given in the TextView (txtFdbData) is deleted (or may be replaced with an empty string?, I do not know).
Following is the post Class
data class Post (
val postName: String="",
val postDescription:String="")
I am working on Android Studio, using Kotlin and Firebase Realtime Database.
You query to database return list of items. So loop through it and try to get Post. Check below:
override fun onDataChange(dataSnapshot: DataSnapshot) {
dataSnapshot.children.forEach {childSnapshot ->
val post = childSnapshot.getValue(Post::class.java)
dbView.text=post?.postName
}
}
getReference("dataID") is not your data node it is your parent node.
Then you have to access their children using getChildren() method.
Change you on data change method with this.
override fun onDataChange(dataSnapshot: DataSnapshot) {
for (postSnapshot : dataSnapshot.getChildren()) {
val post = postSnapshot .getValue(Post::class.java)
dbView.text=post?.postName
}
}
Created next structure in my database, and now want to display data in my list
Tried to add next code in onViewCreated:
databaseReference = FirebaseDatabase.getInstance().reference
val wordsRef = databaseReference?.child("talk-6e3c0")?.child("words")
val valueEventListener = object : ValueEventListener {
override fun onDataChange(dataSnapshot: DataSnapshot) {
topWordsList.clear()
for (wordsSnapshot in dataSnapshot.children) {
val topWord = wordsSnapshot.getValue(TopWord::class.java)
topWord?.let { topWordsList.add(it) }
}
}
override fun onCancelled(databaseError: DatabaseError) {
Log.d("some", "Error trying to get targets for ${databaseError.message}")
}
}
wordsRef?.addListenerForSingleValueEvent(valueEventListener)
Method onDataChanged was called, but i can't get name for example.
My model:
data class TopWord(
val name: String = "",
val description: String = ""
)
You aren't getting something because you are adding the name of your project as a child in the reference and there is no need for that. So please change the following line of code:
val wordsRef = databaseReference?.child("talk-6e3c0")?.child("words")
to
val wordsRef = databaseReference?.child("words")
I just removed the call to .child("talk-6e3c0")?.