I feel that in this code my layout is not being attached.I verified by toast,log.d but nothing worked.Here this I am using for a recycler view view holder.Code is below
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val view = LayoutInflater.from(mContext).inflate(R.layout.posts_layout,parent,false)
return ViewHolder(view)
}
and onBindViewHolder.I user log to check if this method is being used but,its not used
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
firebaseUser = FirebaseAuth.getInstance().currentUser!!
Log.d("binded", true.toString())
val post = mPost[position]
getPublisherInfo(holder.profileImage ,holder.userName , holder.userFullName ,post.getpublisher())
Glide.with(mContext).load(post.getpostId()).placeholder(R.drawable.image).into(holder.postImage)
}
I also checked if my list size id 0 for it to not come.For it use used log and it showed the list size 5 which is correct.This meant that my data is being retrieved from database.So it think that the my layout inflater is not working.The code for it is.
private fun readPosts() {
val postsRef = FirebaseDatabase.getInstance().reference.child("Posts")
postsRef.addValueEventListener(object : ValueEventListener{
#SuppressLint("NotifyDataSetChanged")
override fun onDataChange(snapshot: DataSnapshot) {
postList.clear()
for(snapshot in snapshot.children){
val post = snapshot.getValue(Post::class.java)
for (uid in (followingList as ArrayList<String>)) {
if (post!!.getpublisher().equals(uid)) {
postList.add(post)
}
Log.d("added", postList.size.toString())
Log.d("added", postList.toString())
postAdapter.notifyDataSetChanged()
}
}
}
override fun onCancelled(error: DatabaseError) {}
})
}
My entire adapter code is
package com.u_me_pro.free.Adapters
class PostAdapter(private val mContext: Context,private val mPost: List<Post>) :
RecyclerView.Adapter<PostAdapter.ViewHolder>() {
private lateinit var firebaseUser : FirebaseUser
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val view = LayoutInflater.from(mContext).inflate(R.layout.posts_layout,parent,false)
Log.d("attached layout","true")
return ViewHolder(view)
}
class ViewHolder(#NonNull itemView: View) : RecyclerView.ViewHolder(itemView){
var description: TextView = itemView.findViewById(R.id.description)
var userName: TextView = itemView.findViewById(R.id.user_name_post)
var userFullName: TextView = itemView.findViewById(R.id.user_full_name_post)
var commentCount: TextView = itemView.findViewById(R.id.comment_count)
var likeCount: TextView = itemView.findViewById(R.id.love_count)
var profileImage: RoundedImageView = itemView.findViewById(R.id.user_profile_image_post)
var postImage: RoundedImageView = itemView.findViewById(R.id.post_image)
var like: CardView = itemView.findViewById(R.id.post_image_like)
var comment: CardView = itemView.findViewById(R.id.post_image_comment)
var save: CardView = itemView.findViewById(R.id.post_image_save)
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
firebaseUser = FirebaseAuth.getInstance().currentUser!!
Log.d("binded", true.toString())
val post = mPost[position]
getPublisherInfo(holder.profileImage ,holder.userName , holder.userFullName ,post.getpublisher())
Glide.with(mContext).load(post.getpostId()).placeholder(R.drawable.image).into(holder.postImage)
}
override fun getItemCount(): Int {
return mPost.size
}
private fun getPublisherInfo(profileImage: RoundedImageView, userName: TextView, userFullName: TextView, publisherId: String) {
val usersRef = FirebaseDatabase.getInstance().reference.child("Users").child(publisherId)
Log.d("publisher id",publisherId)
usersRef.addValueEventListener(object :ValueEventListener{
override fun onDataChange(snapshot: DataSnapshot) {
if (snapshot.exists()){
val user = snapshot.getValue(User::class.java)
userName.text = user!!.getFullname()
userFullName.text = user.getFullname()
Glide.with(mContext).load(user.getImage()).placeholder(R.drawable.profile).into(profileImage)
}
}
override fun onCancelled(error: DatabaseError) {
Log.d(TAG, error.getMessage());
}
})
}
}
Please help me out soon.
Thanks!
You're updating the post list and notifying the adapter of a change but it doesn't appear that you're ever actually passing in the updated list to the adapter.
postAdapter.notifyDataSetChanged()
Won't do anything if the actual data in your adapter hasn't changed.
You should add a way to update your post list in the adapter such as
fun setPostData(posts: List<Post>) {
this.adapterPosts = posts
notifyDataSetChanged() // Either call this here or where you were before
}
This would also require you to create a new variable to hold the passed-in list
private var adapterPosts = mPosts
Related
JSON:
people
uid /// the actual uid of each user not a child named uid
imageUrl
Below is the relevant code:
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_homepage)
val user = FirebaseAuth.getInstance().currentUser
if (user != null) {
val query = FirebaseDatabase.getInstance().reference.child("people").child("imageUrl")
val options = FirebaseRecyclerOptions.Builder<DataSnapshot>()
.setQuery(query, DataSnapshot::class.java)
.build()
Log.d("DataSnapshot1", options.toString())
class PhotoViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
val photoImageView = itemView.findViewById<ImageView>(R.id.image_view)
}
val adapter = object : FirebaseRecyclerAdapter<DataSnapshot, PhotoViewHolder>(options) {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): PhotoViewHolder {
val view =
LayoutInflater.from(parent.context).inflate(R.layout.item_photo, parent, false)
return PhotoViewHolder(view)
}
override fun onBindViewHolder(holder: PhotoViewHolder, position: Int, model: DataSnapshot) {
Log.d("DataSnapshot", model.toString())
val imageUrl = model.child("imageUrl").getValue(String::class.java)
if (imageUrl != null) {
Log.d("ImageUrl", imageUrl)
Glide.with(holder.itemView.context)
.load(imageUrl)
.into(holder.photoImageView)
}
}
}
val recyclerView = findViewById<RecyclerView>(R.id.cycle)
recyclerView.layoutManager = LinearLayoutManager(this)
recyclerView.adapter = adapter
adapter.startListening()
}
}
What I know: The problem is not in the XMLs of this page or the image to be displayed on the recycler view. Also, ("ImageUrl") and "DataSnapshot" don't print out. But "DataSnapshot1" does print out.
I assume you're trying to list all the items under the people node?
In that case, you need to update your query to:
val query = FirebaseDatabase.getInstance().reference.child("people")
I don't think FirebaseUI supports DataSnapshot as a model class, so I would suggest creating a separate class to hold the data. I have created a Person class as an example:
data class Person(var imageUrl: String? = null)
And then your options would become:
val options = FirebaseRecyclerOptions.Builder<Person>()
.setQuery(query, Person::class.java)
.build()
And your adapter:
val adapter = object : FirebaseRecyclerAdapter<Person, PhotoViewHolder>(options) {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): PhotoViewHolder {
val view =
LayoutInflater.from(parent.context).inflate(R.layout.item_photo, parent, false)
return PhotoViewHolder(view)
}
override fun onBindViewHolder(holder: PhotoViewHolder, position: Int, model: Person) {
val imageUrl = model.imageUrl
if (imageUrl != null) {
Log.d("ImageUrl", imageUrl)
Glide.with(holder.itemView.context)
.load(imageUrl)
.into(holder.photoImageView)
}
}
}
This question already has answers here:
How to return DataSnapshot value as a result of a method?
(6 answers)
getContactsFromFirebase() method return an empty list
(1 answer)
Setting Singleton property value in Firebase Listener
(3 answers)
Closed 1 year ago.
Hello I am trying to implement a RecyclerView of users that are in my RealtimeDatabase, but this code dosen't work and I dont know why. Here is the code for Activity.
class NewMessageActivity : AppCompatActivity() {
private val TAG = "NewMessageActivityTag/////////////////////////////"
private lateinit var binding : ActivityNewMessageBinding
private lateinit var realtimeDatabase : FirebaseDatabase
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityNewMessageBinding.inflate(layoutInflater)
setContentView(binding.root)
supportActionBar?.title = "New Message"
realtimeDatabase = FirebaseDatabase.getInstance("https://firechat-931d2-default-rtdb.asia-southeast1.firebasedatabase.app/")
val users = fetchUsers()
Log.d(TAG,"vkgjhbiuglkjhglioiuhghubgDone2 $users")
binding.rvNewMessageActivity.adapter = UsersAdpater(this,users)
binding.rvNewMessageActivity.layoutManager = LinearLayoutManager(this,LinearLayoutManager.VERTICAL,false)
}
private fun fetchUsers() : ArrayList<UserInfo> {
val ref = realtimeDatabase.getReference("/users")
val userList = ArrayList<UserInfo>()
Log.d(TAG,"pidsnigfngadsnfpoin")
ref.addListenerForSingleValueEvent(object : ValueEventListener {
override fun onDataChange(snapshot: DataSnapshot) {
if(snapshot.exists()) {
Log.d(TAG,"$snapshot")
for(child in snapshot.children){
val tempchild = child.getValue(UserInfo::class.java)
Log.d(TAG,"$tempchild")
userList.add(tempchild ?: UserInfo("default_UID","default_email","default_name","default_picurl"))
}
}
}
override fun onCancelled(error: DatabaseError) {
Log.d(TAG,"$error ${error.message}")
}
})
Log.d(TAG,"$userList")
// if(userList.isEmpty()) {
// for(i in 1..10) {
// userList.add(UserInfo("default_UID$i","default_email$i","default_name$i","https://firebasestorage.googleapis.com/v0/b/firechat-931d2.appspot.com/o/ProfileImages%2FL5yOgELQtmXdUcnxf7S6Iqs1OsN2.profileImage?alt=media&token=3573195b-a5bb-499f-a79b-7191d5ad2655"))
// }
// }
return userList
}
}
Now I'll add the data class code
1
Now I'll add the adapter
class UsersAdpater(val context : Context, val gotData : ArrayList<UserInfo>) : RecyclerView.Adapter<UsersAdpater.UserViewHolder>() {
private var data : ArrayList<UserInfo> = gotData
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): UserViewHolder {
val view = LayoutInflater.from(parent.context).inflate(R.layout.item_user_newmessasgesactivity,parent,false)
return UserViewHolder(view)
}
override fun onBindViewHolder(holder: UserViewHolder, position: Int) {
holder.username.text = data[position].name
holder.useremail.text = data[position].email
Glide.with(context).load(data[position].profilePicUrl).into(holder.userImage).onLoadFailed(ContextCompat.getDrawable(context,R.drawable.profilepicnormall))
holder.entireLayout.setOnClickListener {
//TODO("IMPLEMENT OPENING A NEW CHAT WITH THIS USER")
Log.d("NewMessagesActivity","${data[position].toString()}")
}
}
override fun getItemCount(): Int {
return data.size
}
private fun updateList(userList : ArrayList<UserInfo>) {
data = userList
}
inner class UserViewHolder(private val itemView : View) : RecyclerView.ViewHolder(itemView) {
val username = itemView.findViewById<TextView>(R.id.item_rvnma_username)
val useremail = itemView.findViewById<TextView>(R.id.item_rvnma_email)
val userImage = itemView.findViewById<ImageView>(R.id.item_rvnma_image)
val entireLayout = itemView
}
}
// In the Log
2 As you can see the the function fetchUsers() has already returned an empty list and the data is logged after that. Why so ? And also why is it returning an empty list when it logs data for every user?
Is it because the fetching of users takes time? Do I need to use Coroutines?
So I need to show only three objects from my Firebase database on the screen. How can this be implemented?
I retrieve my data using this logic with adapter.
retrieveData()
setData(recyclerView)
private fun setData(rec_view:RecyclerView) {
val query = FirebaseDatabase.getInstance().reference.child("News")
val options = FirebaseRecyclerOptions.Builder<News>()
.setQuery(query, News::class.java)
.build()
adapter = object:FirebaseRecyclerAdapter<News, NewsViewHolder>(options){
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): NewsViewHolder {
Log.d("onCreateViewHolder_n", "onCreateViewHolder")
val newsView = LayoutInflater
.from(parent.context)
.inflate(R.layout.new_card_new, parent, false)
return NewsViewHolder(newsView)
}
override fun onBindViewHolder(holder: NewsViewHolder, position: Int, model: News) {
holder.setIsRecyclable(false)
holder.title.text = model.text
holder.timestamp.text = model.timestamp
holder.setNewsClickListener(object: NNewsClickListener {
override fun onClick(view: View, position: Int) {
startActivity(Intent(Intent.ACTION_VIEW).setData(Uri.parse(model.link)));
}
})
}
}
rec_view.adapter = adapter
}
private fun retrieveData() {
items.clear()
val db = FirebaseDatabase.getInstance()
.reference
.child("News")
db.addListenerForSingleValueEvent(object :ValueEventListener{
override fun onCancelled(error: DatabaseError) {
Log.d("ERROR", "" + error.message)
}
override fun onDataChange(snapshot: DataSnapshot) {
for(item_newsSnapShot in snapshot.children)
{
val item_news = item_newsSnapShot.getValue(News::class.java)
items.add(item_news!!)
}
}
})
}
I found out somewhere that I should use getItemCount() or something like this but I'm not sure. If you have any questions regarding my problem, feel free to ask.
If the rest of your code already works, you can limit Firebase to retrieving only 3 items with:
val db = FirebaseDatabase.getInstance()
.reference
.child("News")
.limitToFirst(3)
I recommend checking out the documentation on sorting and filtering data.
I'm having trouble to delete one item in my Arraylist from Firebase Database using RecyclerView. There is an AlertDialog which I can see when I'm clicking on it, but it doesn't delete the Item. I think the problem is, that I cannot get the postID correctly. But I tried it in many ways, and within the database Reference I wasn't able to do it right.
This is where I add the Post to the database:
val ref = FirebaseDatabase.getInstance().reference.child("Posts")
val postId = ref.push().key
And here you can see my PostsAdapter
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val view = LayoutInflater.from(mContext).inflate(R.layout.posts_layout, parent, false)
return ViewHolder(view)
}
override fun getItemCount(): Int {
return mPosts.size
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
FirebaseUser = FirebaseAuth.getInstance().currentUser
val posts = mPosts[position]
holder.title.text = posts.getTitle()
holder.content.text = posts.getContent()
holder.deletePost.text = posts.getPostId()
ownerInfo(holder.name, posts.getOwner())
}
inner class ViewHolder(#NonNull itemView: View) : RecyclerView.ViewHolder(itemView),
View.OnClickListener {
override fun onClick(p0: View?) {
val intent = Intent(itemView.context, DeletePostActivity::class.java)
// here pass id through intent
intent.putExtra("postId", R.id.deletePost)
itemView.context.startActivity(intent)
}
var title: TextView
var content: TextView
var owner: TextView
var name: TextView
var deletePost: Button
init{
title = itemView.findViewById(R.id.post_title)
content = itemView.findViewById(R.id.post_content)
owner = itemView.findViewById(R.id.post_owner)
name = itemView.findViewById(R.id.post_owner)
deletePost = itemView.findViewById(R.id.post_delete)
deletePost.setOnClickListener{
AlertDialog.Builder(mContext)
.setTitle("Löschen")
.setMessage("Wollen Sie diesen Post wirklich löschen?")
.setCancelable(true)
.setPositiveButton("Ja") { dialog, which ->
notifyItemRemoved(adapterPosition)
notifyItemRangeChanged(adapterPosition, mPosts.size)
val postsRef = FirebaseDatabase.getInstance().reference.child("Posts").child("postID")
postsRef.child("postID").removeValue()
}
.create()
.show()
}
}
}
Actually you are not passing any postID to delete. Check below
Instead of
val postsRef = FirebaseDatabase.getInstance().reference.child("Posts").child("postID")
postsRef.child("postID").removeValue()
use
val postsRef = FirebaseDatabase.getInstance().reference.child("Posts").child(deletePost.text)
postsRef.removeValue()
How do I get key in kotlin in RecyclerView to send it to another activity?
I tried using getKey() and position but it doesn't work.
Here is my code:
class RecyclerAdapter (val userlist:ArrayList<RecyClass>,ccc: Context): RecyclerView.Adapter<RecyclerAdapter.ViewHolder>() {
var mcontext =ccc
val Postdata = java.util.ArrayList<RecyClass>()
lateinit var ref:DatabaseReference
override fun getItemCount(): Int {
return userlist.size
}
override fun onBindViewHolder( holder: ViewHolder?, position: Int) {
val user: RecyClass = userlist[position]
ref = FirebaseDatabase.getInstance().getReference(user.toString())
holder?.txtviewdesc?.text = user.desc
Picasso.with(mcontext).load(user.image).into(holder?.imageviewx)
holder?.setOncustomcilcklistner(object :Custumclicklistner33{
override fun oncustomOnClickListner(view: View, pos: Int) {
}
})
}
override fun onCreateViewHolder(parent: ViewGroup?, viewType: Int): ViewHolder {
this.Postdata
this.mcon
val v = LayoutInflater.from(parent?.context).inflate(R.layout.layoutrcview,parent,false)
return ViewHolder(v,mcon,userlist)
}
class ViewHolder(itemview: View,ccc2:Context,userlist: ArrayList<RecyClass>): RecyclerView.ViewHolder(itemview), View.OnClickListener{
var mCustIemClick5: Custumclicklistner33?=null
var txtviewdesc: TextView
var mcon =ccc2
var userdata =userlist
var imageviewx: ImageView
init {
this.userdata
this.mcon
txtviewdesc = itemview.findViewById<TextView>(R.id.editTextdesc)
imageviewx = itemview.findViewById<ImageView>(R.id.imgvw)
itemview.setOnClickListener(this)
}
fun setOncustomcilcklistner(customclick5: Custumclicklistner33){
this.mCustIemClick5=customclick5
}
override fun onClick(view: View?) {
this.mCustIemClick5!!.oncustomOnClickListner(view!!,adapterPosition)
val pos = adapterPosition
val ref =FirebaseDatabase.getInstance().getReference(pos.toString()).key.toString()
Toast.makeText(mcon,ref,Toast.LENGTH_LONG).show()
var postDetail = this.userdata[pos]
val kkk = Intent(this.mcon,ProfileActivity::class.java)
kkk.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
this.mcon.startActivity(kkk)
}
}
}
fun onclick takes to next activity but it takes post's key. How to get it?
getref and postiton is not working in fun onclick but it works on bindviewholder.
You need to use PostData[position] to get the object that current position and then a key/field from that object that you can reference.