HashMap is null so i cant get my data shown in the emulator from Firebase database - android

Android studio showed a warning so with ALT + ENTER the code
val name = data[USERNAME] as String
became
val name = data?.get(USERNAME) as String
but my emulator is still crashing
thoughtsCollectionRef.get()
.addOnSuccessListener { snapshot ->
for(document in snapshot.documents){
val data = document.data
//this is my code after listening to android studio
val name = data?.get(USERNAME) as String
val timestamp = data?.get(TIMESTAMP) as Date
val thoughtTxt = data?.get(THOUGHT_TXT) as String
val numLikes = data?.get(NUM_LIKES) as Long
val numComments = data?.get(NUM_COMMENTS) as Long
val documentId = document.id
//I edited every other variable with the safecall ?.get() and its still crashing
val newThought = Thought(name,timestamp,thoughtTxt,numLikes.toInt(),numComments.toInt(),
documentId)
thoughts.add(newThought)
}
thoughtsAdapter.notifyDataSetChanged()

The data?.get(TIMESTAMP) call returns a Firebase Timestamp object. So instead of casting it to Date, you should cast it to com.google.firebase.Timestamp:
// imports
import com.google.firebase.Timestamp
...
// rest of the code
val timestamp = data?.get(TIMESTAMP) as? Timestamp
If you want to end up with a Date object, you can use the Timestamp method toDate():
val date = timestamp?.toDate()
Also note that you should use a safe casting operator as? instead of as in this case:
val name = data?.get(USERNAME) as? String
val timestamp = data?.get(TIMESTAMP) as? Timestamp
val thoughtTxt = data?.get(THOUGHT_TXT) as? String
val numLikes = data?.get(NUM_LIKES) as? Long
val numComments = data?.get(NUM_COMMENTS) as? Long
The data?.get(KEY) may produce a null object, which can't be cast to any type and the operation will result in a crash.

Related

Arraylist remains null even when data is being passed to it

I'm working on a firebase chatting app. I want to maintain chats between two different users for this I'm creating a parent node as +923478302658#Chat and within it, a child node as +923478302658-+923065015216 within it messages for both participants.
Here is my Chat Model:
class AllChatsModel {
var chatID: String? = null
var chatStarterName: String? = null
var chatRecieverName: String? = null
var chatStartTD: String? = null
var chatLastMessage: String? = null
var chatLastMsgTime: String? = null
var chatHeadActive: Boolean? = null
var chatMessages: ArrayList<MessageModel>? = null
}
And here is the function to send a message:
private fun sendMessage(message: String) {
val dateFormat = SimpleDateFormat("dd MMMM, yyyy 'at' HH:mm aaa")
val calendar = Calendar.getInstance()
val currentTime: String = dateFormat.format(calendar.time)
val chatID = databaseReference!!.push().key
val chatModel = AllChatsModel()
chatModel.chatStarterName = (sharedPreference?.userName)
chatModel.chatRecieverName = signUpEntity?.userUID
chatModel.chatStartTD = currentTime
chatModel.chatLastMessage = message
chatModel.chatLastMsgTime = currentTime
val chatMessagesList: ArrayList<MessageModel>? = chatModel?.chatMessages // debugs gives null here
val messageID = databaseReference!!.push().key
val messageModel = MessageModel()
messageModel.messageID = messageID
messageModel.messageText = message
messageModel.messageTime = currentTime
messageModel.msgSenderID = FirebaseAuth.getInstance().uid
messageModel.msgSenderName = (sharedPreference?.userName)
messageModel.msgSenderNo = (currentUserNo)
messageModel.msgReceiverID = signUpEntity?.userUID
messageModel.msgReceiverName = signUpEntity?.userName
messageModel.msgReceiverNo = signUpEntity?.userPhone
chatMessagesList?.add(messageModel) // here chatMessagesList is null
chatModel.chatMessages = chatMessagesList
FirebaseDatabase.getInstance().reference.child("${currentUserNo}#Chat")
.child("${currentUserNo}-${signUpEntity?.userPhone}")
.child("ChatMessages").setValue(chatModel)
txtInputMsg.setText("")
}
I want to get the firebase nodes structure like this but the app crashes. Why I'm not getting the data like that in the attached pic.
[1]: https://i.stack.imgur.com/QOW8c.png
I guess there is an error in how you define val chatMessagesList variable in sendMessage() function. Try to fix it to:
val chatMessagesList: ArrayList<MessageModel> = chatModel?.chatMessages ?: ArrayList<MessageModel>()
Using an Elvis operator ?: we guarantee that chatMessagesList variable won't be null.
When you write this code:
val chatMessagesList: ArrayList<MessageModel>? = chatModel?.chatMessages // debugs gives null here
chatModel?.chatMessages property isn't created yet, so it is null.
Just replace it with the next line and it will work:
val chatMessagesList: ArrayList<MessageModel> = chatModel?.chatMessages ?: ArrayList<MessageModel>()
Or you can just write:
val chatMessagesList = ArrayList<MessageModel>()
because you create a new object of AllChatsModel class in sendMessage() function, that's why chatModel?.chatMessages will always be null until it is initialized.

I want to show a data whose values I have determined myself in text

calculateButton.setOnClickListener {
val panelC = binding.panelCount.text.toString()
val panelS = binding.panelSize.text.toString()
val landS = binding.landSlope.text.toString()
val landSi = binding.landSize.text.toString()
val cit = binding.city.text.toString()
val sun = (1000).toInt()
val air = (1.25).toFloat()
val cel = (25).toInt()
val verim = ((sun * air)/ cel).toString().toDouble()
if (panelC.equals("") || panelS.equals("")|| landS.equals("")|| landSi.equals("")||cit.equals("")){
Toast.makeText(requireContext(),"Alanları Doldurunuz.", Toast.LENGTH_SHORT).show()
}
else{
val action = SignUpCalculateFragmentDirections.actionSignUpCalculateFragmentToDataFragment()
Navigation.findNavController(view).navigate(action)
}
val postMap = hashMapOf<String, Any>()
postMap.put("Panel Sayisi",binding.panelCount.text.toString())
postMap.put("Panel Boyutu",binding.panelSize.text.toString())
postMap.put("Arazi Eğimi",binding.landSlope.text.toString())
postMap.put("Arazi Boyutu",binding.landSize.text.toString())
postMap.put("Şehir",binding.city.text.toString())
postMap.put("date", Timestamp.now())
postMap.put("verim",verim.toString().toDouble())
firestore.collection("Posts").add(postMap).addOnFailureListener {
}.addOnFailureListener {
Toast.makeText(requireContext(),it.localizedMessage,Toast.LENGTH_SHORT).show()
}
There is a calculatePage Fragment Codes. On this page, I am trying to make a yield calculation based on the data I receive from the user. However, I need to add the values that are kept constant in the efficiency calculation, such as "sun", "cel", "air" that I defined in the code. I wrote a random operation there as an example. To see if I can write inside the text I'm trying to print without getting any errors. But the app crashed.
private fun getData(){
firestore.collection("Posts").addSnapshotListener { value, error ->
if (error!=null){
Toast.makeText(requireContext(),error.localizedMessage,Toast.LENGTH_SHORT).show()
}else{
if (value !=null){
if (!value.isEmpty){
val documents = value.documents
for (document in documents){
val pc = document.get("Panel Sayisi") as String
val ps = document.get("Panel Boyutu") as String
val ls = document.get("Arazi Eğimi") as String
val lsi = document.get("Arazi Boyutu") as String
val c = document.get("Şehir") as String
val v = document.get("verim") as Double
val post = Post(pc,ps,ls,lsi,c,v)
postArrayList.add(post)
}
}
}
}
val db = FirebaseFirestore.getInstance()
db.collection("Posts").orderBy("date",Query.Direction.DESCENDING).limit(1)
.get()
.addOnCompleteListener {
val result : StringBuffer = StringBuffer()
if (it.isSuccessful){
for (document in it.result){
result.append(document.data.getValue("verim"))
}
verimText.setText(result)
}
}
On this page, I added the values I defined in my class named 'post' to the postList and added them to Firestore.
data class Post(val pc: String, val ps: String, val ls: String, val lsi: String, val c: String, val v : Double)
#ServerTimestamp
var date: Date? = null
This is my post class
The error is like this: java.lang.NullPointerException: null cannot be cast to non-null
type kotlin.Double
As I explained at the beginning of my question, what I am trying to do is using both the data such as "panelCount", "panelSize" that I get from the user and the "sun", "cel", "air" values that are defined as constants, using the "verimText.setText(result)" in the DataFragment page. I need to show this calculation to the user.
The user enters values such as 'Panel Sayisi', 'Panel Boyutu' that should be used while calculating on the calculation page. I need to show this to the user in verimText using both this data and the 'cel', 'sun', 'air' constants that I wrote in the first code.
PS: verim: 20000 value is the result of hypothetical values that I wrote in the first code. In this part, I need to make a calculation using the other data entered by the user and these constant values and show it in the verimText.

Type mismatch: inferred type is com.google.firebase.firestore.auth.User but com.example.socialmediaapp.model.User was expected

Error is showing for the user when passed in post i.e val post = Post(text, user, currentTime)
class PostDao {
private val db = FirebaseFirestore.getInstance()
private val postCollection = db.collection("posts")
private val auth = Firebase.auth
fun addPost(text:String){
val currentUserId = auth.currentUser!!.uid
GlobalScope.launch {
val userDao = UserDao()
//getting actual user document from the task through user id
val user = userDao.getUserById(currentUserId).await().toObject(User::class.java)!!
val currentTime = System.currentTimeMillis()
val post = Post(text, user, currentTime)
}
}
}
Here is the Post data class :
data class Post(
val text:String = "",
val createdBy: User = User(),
val createdAt:Long = 0L,
val likedBy: ArrayList<String> = ArrayList()
)
Please help me solve this issue.
Thank you !
This is because you are not using same user object at both of the places. You need to declare and get same type of USER class in your code.
You are trying to get the value of com.google.firebase.firestore.auth.User but com.example.socialmediaapp.model.User is expected as per your code.

how to get position of deleted Firestore Data that have been deleted from console (outside source) to update Or notify the adapter

I have this app that someone can delete his document at any time so if he deletes the document I want every other user to get updated the document has been removed and remove the document from the listView, it's more like a Food Ordering app so the user order could be taking by another Driver so the document will no longer be available for other users, I want to update the recyclerView Whenever a user deletes a document, so how to get the position without clicking how to detect that change to get the position, Sorry if I couldn't explain much I'm Using Groupie Adapter
val ref = firestore.collection("orders").whereNotEqualTo("userUid", uid)
val adapter = GroupAdapter<GroupieViewHolder>()
ref.addSnapshotListener { value, error ->
if (error != null){
return#addSnapshotListener
}
value?.documentChanges?.forEach {
if (it.type == DocumentChange.Type.ADDED) {
val userUid = it.document.data.get("userUid") as String
val userPhone = it.document.data.get("phone") as String
val userName = it.document.data.get("name") as String
val time = it.document.data.get("time") as String
val marketName = it.document.data.get("marketName") as String
val amount = it.document.data.get("amount") as String
val storeimgUrl = it.document.data.get("storeImg") as String
val order = it.document.data.get("order") as String
val userImg = it.document.data.get("userImg") as String
adapter.add(DriverOrders(userUid, userPhone, userName, time, marketName, amount, storeimgUrl, order, userImg))
adapter.notifyDataSetChanged()
}
if(it.type == DocumentChange.Type.REMOVED){
// here Wher I'm trying to get the position of deleted Or removed data
if (it.document.id == DriverOrders.docId){
adapter.notifyItemRemoved(it.oldIndex)
}
}
}
recyclerview_driverorders.adapter = adapter
}
class DriverOrders(val userUid: String, val userPhone: String,
val userName: String, val time: String,
val marketName: String, val amount: String, val storeimgUrl: String, val order: String,
val userImg: String):Item<GroupieViewHolder>() {
override fun getLayout(): Int {
return R.layout.driver_row
}
override fun bind(viewHolder: GroupieViewHolder, position: Int) {
viewHolder.itemView.driverorders_sName.text = marketName
viewHolder.itemView.driverorders_order.text = order
viewHolder.itemView.driverorders_time.text = Date
Picasso.get().load(storeimgUrl).fit().into(viewHolder.itemView.driverorders_sImg)
}
}

How to use TimeAgo format with firestore or realtime database?

I am using a Github Library to Display time in a TextView as the format like just now, yesterday, time ago... etc. It displays the time as I want. But the problem is that the time is not changing as it was just now at the moment of post-it remains that forever.
Model class for postAdapter
class Post {
private var date: String = ""
constructor(date: Long) {
fun getDate(): String
{
return date
}
//Initialization according to the library
val timeInMillis = System.currentTimeMillis()
val timeAgo = TimeAgo.using(timeInMillis)
//saving the data to firestore
val fStore: FirebaseFirestore = FirebaseFirestore.getInstance()
val post = Post(title, description, date = timeAgo)
fStore.collection("Posts").document()
.set(post)
.addOnSuccessListener{...}
Retrieving the data from the Firestore
private fun postInfo(title: TextView, description: TextView, date: TextView) {
val postRef = FirebaseFirestore.getInstance().collection("Posts").document()
postRef.get()
.addOnSuccessListener { documentSnapshot ->
if (documentSnapshot != null && documentSnapshot.exists()) {
val post = documentSnapshot.toObject(Post::class.java)
date.text = post?.getDate()
title.text = post?.getTitle()
description.text = post?.getDescription()
}
}
}
What you do is using a library to convert a date to a string, and then set the TextView text to that string. Strings are only lists of chars and they have no "consciousness" about what they mean or if they ever need to change/update.
I would suggest using a RelativeTimeTextView from android-ago. Once you set a reference time to that view, there's some code inside that will automatically trigger updates for you.
https://github.com/curioustechizen/android-ago
Edit: you're also doing conversion from timeInMillis: Long to date: String at the moment of storage in firestore. You should instead store timeInMillis as is (Long value) and then when reading use it as argument of relativeTimetextView.setReferenceTime(timeInMillis).

Categories

Resources