Populating Data Class via Simple Firebase Calls - android

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

How to pass key as a value through a database model class in Kotlin

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!!)

Get firebase snapshot data in Kotlin Android

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)

How to retrieve nested data structure from Firebase Realtime Database on Kotlin

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>()

Retrieve data from Firebase on Android Studio

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
}
}

Display data from Firebase Realtime Database

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")?.

Categories

Resources