Update firestore data from populated recycler View - kotlin

I want to update firestore data which I have got in a Recycler view.
Recycler View Activity Code
class AdminActivity : AppCompatActivity() {
private val dB = Firebase.firestore
private lateinit var userRecyclerView: RecyclerView
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
supportActionBar?.title = "Admin Panel"
userRecyclerView = findViewById(R.id.user_list)
userRecyclerView.layoutManager = LinearLayoutManager(this)
userRecyclerView.setHasFixedSize(true)
val query = dB.collection("users")
val options = FirestoreRecyclerOptions.Builder<User>().setQuery(query, User::class.java)
.setLifecycleOwner(this).build()
//adapter
val adapter = object : FirestoreRecyclerAdapter<User, UserViewHolder>(options) {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): UserViewHolder {
val view = LayoutInflater.from(this#AdminActivity)
.inflate(R.layout.user_item, parent, false)
return UserViewHolder(view)
}
override fun onBindViewHolder(holder: UserViewHolder, position: Int, model: User) {
val nameTv: TextView = holder.itemView.findViewById(R.id.name_textview)
val idTv: TextView = holder.itemView.findViewById(R.id.id_textview)
val phoneTv: TextView = holder.itemView.findViewById(R.id.phone_textview)
nameTv.text = model.name
idTv.text = model.id
phoneTv.text = model.phone
holder.itemView.setOnClickListener {
val intent = Intent(baseContext, AdminViewActivity::class.java)
startActivity(intent)
}
}
}
userRecyclerView.adapter = adapter
}
}
I want to update the data when i click on the holder.
Only update the data of the user whose recycler view I clicked.
Firestore Database Image

Related

E/RecyclerView: No adapter attached; skipping layout while getting the data from Google Spreadsheet

I am trying to get the data from the Google Spreadsheet and display it in a recyclerView in Kotlin. But I am getting the error as in the title.
I know there are many questions about the error 'E/RecyclerView: No adapter attached'. I spent hours going through all the posts and made changes to my code. But I couldn't fix the issue as I am not an expert coder.
Following is SalesData.kt
class SalesData : AppCompatActivity() {
private lateinit var binding: ActivitySalesDataBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivitySalesDataBinding.inflate(layoutInflater)
setContentView(binding.root)
val salesList = arrayListOf<SalesDataModel>()
binding.rvSalesData.layoutManager = LinearLayoutManager(applicationContext)
binding.rvSalesData.setHasFixedSize(true)
val adapter = SalesDataRecyclerAdapter(applicationContext,salesList)
binding.rvSalesData.adapter = adapter
val queue = Volley.newRequestQueue(this)
val url = "https://script.google.com/macros/s/fssfsdffdfhfhPPEWVM2FeIH3gZY5kAnb6JVeWpg2Xedfgt443534tdfg43t/exec"
val jsonObjectRequest = object: JsonObjectRequest(Request.Method.GET,url,null,Response.Listener {
val data = it.getJSONArray("items")
for(i in 0 until data.length()){
val salesJasonObject = data.getJSONObject(i)
val salesObject = SalesDataModel(
salesJasonObject.getString("Date"),
salesJasonObject.getString("Branch"),
salesJasonObject.getDouble("NetSale"),
salesJasonObject.getDouble("Profit"),
)
salesList.add(salesObject)
adapter.notifyDataSetChanged()
}
},Response.ErrorListener { }
){
override fun getHeaders(): MutableMap<String, String> {
return super.getHeaders()
}
}
}
}
and this is the adapter class SalesDataRecyclerAdapter.kt
class SalesDataRecyclerAdapter(val context: Context, private val saleDataList:ArrayList<SalesDataModel>)
:RecyclerView.Adapter<RecyclerView.ViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
return MyViewHolder(
SalesDataLayoutBinding.inflate(
LayoutInflater.from(
parent.context
), parent, false
)
)
}
override fun getItemCount(): Int {
return saleDataList.size
}
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
val model = saleDataList[position]
if (holder is MyViewHolder){
holder.binding.tvSales.text = model.salesAmount.toString()
holder.binding.tvBranch.text = model.branch
holder.binding.tvDate.text = model.date
holder.binding.tvProfit.text = model.profit.toString()
}
}
private class MyViewHolder(val binding: SalesDataLayoutBinding) : RecyclerView.ViewHolder(binding.root)
}

How to pass Firebase Realtime database images from reyclerview to image view in another activity. KOTLIN

I have Firebase Realtime Database images displayed in a reyclerview. When users click that image, I want it to send the image to another activity's IMAGEVIEW and open that activity at the same time.
These are pictures of an example I saw on Youtube
As you can see in the second picture. It sent the data from the recyclerview to the imageview in the activity and opened that activity.
My adapter class
class AbstractAdapter(private val mContext: Context, private val abstractList: ArrayList<Abstract>) :
RecyclerView.Adapter<AbstractAdapter.ViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val view = LayoutInflater.from(parent.context).inflate(R.layout.abstract_image_view, parent, false)
return ViewHolder(view)
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
holder.imageView.setOnClickListener {
val intent = Intent(mContext, PreviewActivity::class.java)
intent.putExtra("abstract", abstractList[position].abstract.toString())
mContext.startActivity(intent)
}
holder.download_btn.setOnClickListener { }
Glide.with(mContext)
.load(abstractList[position].abstract)
.into(holder.imageView)
}
override fun getItemCount(): Int {
return abstractList.size
}
class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
val imageView: ImageView = itemView.findViewById(R.id.abstractImageView)
val download_btn: Button = itemView.findViewById(R.id.abstractDownloadBtn)
}
companion object {
private const val Tag = "RecyclerView"
}
Activity to receive image
class PreviewActivity : AppCompatActivity() {
private lateinit var previewImage: ImageView
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_preview)
previewImage = findViewById(R.id.preview_image)
val previewImage: ImageView = findViewById(R.id.preview_image)
val bundle :Bundle? = intent.extras
val preview = bundle!!.getString("abstract")
}
Data model
class Abstract(var abstract: String? = null) {
}
I've tried running this code, but it doesn't show my image in the next activity. The Logcat doesn't give me any error, because according to it my code is running perfectly except that it's not showing the image in the next activity. I must be missing something, but I don't know what it is.
You have to set the image url to ImageView using Glide in second activity like this:
class PreviewActivity : AppCompatActivity() {
private lateinit var previewImage: ImageView
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_preview)
previewImage = findViewById(R.id.preview_image)
val previewImage: ImageView = findViewById(R.id.preview_image)
val bundle :Bundle? = intent.extras
val preview = bundle!!.getString("abstract")
Glide.with(this)
.load(preview)
.into(previewImage)
}

RecyclerView doesn't display data but onBindViewHolder never called

I'm using recyclerView to display my data but anything is displaying. The onBindViewHolder is never called and the onCreateViewHolder also.
I initialize the adapter in the viewModel with the data which I got from room but anything is displaying. The data in the viewModel is there when I want give it to the adaptater.
There's the adaptater,
class CountryInfoAdapter : RecyclerView.Adapter<TextItemViewHolder>() {
var data = listOf<DevByteCountryProperty>()
set(value) {
field = value
notifyDataSetChanged()
}
override fun getItemCount() = data.size
override fun onBindViewHolder(holder: TextItemViewHolder, position: Int) {
val item = data[position]
holder.textView.text = item.name.toString()
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): TextItemViewHolder {
//The inflater knows how to create views from XML layout. The context is the context of the RecyclerView.
val layoutInflater = LayoutInflater.from(parent.context)
val view = layoutInflater.inflate(R.layout.text_item_view, parent, false) as TextView
Timber.i("Data from adaptater : ${data.toString()}")
return TextItemViewHolder(view)
}
}
There is the Fragment,
class CountryInfoFragment : Fragment() {
private lateinit var viewModel: CountryInfoViewModel
private lateinit var viewModelFactory: CountryInfoViewModelFactory
private lateinit var binding: FragmentCountryInfoBinding
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?): View? {
binding = DataBindingUtil.inflate(inflater,
R.layout.fragment_country_info,container,false)
val application = requireNotNull(this.activity).application
viewModelFactory = CountryInfoViewModelFactory(application)
viewModel = ViewModelProvider(this,viewModelFactory).get(CountryInfoViewModel::class.java)
binding.viewModel = viewModel
val adapter = CountryInfoAdapter()
viewModel.countriesProperty.observe(viewLifecycleOwner, Observer {
it?.let {
adapter.data = it
}
})
binding.countryList.adapter = adapter
binding.lifecycleOwner = viewLifecycleOwner
setHasOptionsMenu(true)
return binding.root
}
}
Please try below code, setting up layout manager before assigning adapter to recyclerView
binding.countryList.layoutManager = LinearLayoutManager(this)
binding.countryList.adapter = adapter

Receive data from Adapter to DetailsActivity?

I want to know how I can receive the data from adapter (recyclerview) to DetailsActivity. I tried many times but the images from recyclerview doesn't show in DetailsActivity.
this is my code.
ImageAdapter
class ImageAdapter (private var items:List<Item>, private val context:Context):
RecyclerView.Adapter<ImageAdapter.ViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int):ViewHolder {
return ViewHolder(
LayoutInflater.from(context).inflate(R.layout.item, parent, false)
)
}
override fun getItemCount(): Int {
return items.size
}
override fun onBindViewHolder(holder: ImageAdapter.ViewHolder, position: Int) {
val item = items[position]
Picasso.get().load(item.imageUrl).into(holder.imageView)
holder.imageView.setOnClickListener {
val intent = Intent(context, DetailsActivity::class.java)
intent.putExtra("iImages", item.imageUrl)
context.startActivity(intent)
}
}
class ViewHolder(view:View):RecyclerView.ViewHolder(view) {
val imageView : ImageView = view.findViewById(R.id.imageView)
}
}
DetailsActivity
class DetailsActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_details)
val aImageView = intent.getIntExtra("iImages", 0)
details_image.setImageResource(aImageView)
}
}
RecyclerActivity
class RecyclerActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_recycler)
val storage = FirebaseStorage.getInstance()
val storageRef = storage.reference.child("wallpapers")
val imageList : ArrayList<Item> = ArrayList()
//progressBar.visibility = View.VISIBLE
val listAllTask : Task<ListResult> = storageRef.listAll()
listAllTask.addOnCompleteListener { result ->
val items: List<StorageReference> = result.result!!.items
//add cycle for add image url to list
items.forEachIndexed { index,item ->
item.downloadUrl.addOnSuccessListener {
Log.d("item", "$it")
imageList.add(Item(it.toString()))
}.addOnCompleteListener {
recyclerview.adapter = ImageAdapter(imageList, this)
recyclerview.layoutManager = LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false)
//progressBar.visibility = View.GONE
}
}
}
}
}
Item
data class Item(
var imageUrl: String
)
The problem is this line:
details_image.setImageResource(aImageView)
You are setting a resource int but what you pass seems to be a url, so instead load the "iImages" value with Picasso for that view
Edit: Replace this:
val aImageView = intent.getIntExtra("iImages", 0)
details_image.setImageResource(aImageView)
with this
val retrievedImageUrl = intent.getIntExtra("iImages", 0)
Picasso.get().load(retrievedImageUrl).into(details_image)
The Answer
val imageView : ImageView = findViewById(R.id.details_image)
Glide.with(this).load(intent.getStringExtra("iImages")).into(imageView)

RecyclerView onClick in kotlin

I'm new android learner, I'm trying to make a RecyclerView contains of List of (Stories Title, and Stories images).
When you click on an item in the RecyclerView it should open a new activity called ChildrenStoriesPreview contains of ScrollView which have ImageView to put the Story Image in it and TextView to put the Text of the Story in it.
the problem is that I don't know how to set ocItemClickListener to know which item is clicked and how the new activity will contain information depending on this item? Could you please help me?
here is my Main.kt
class MainChildrenStories : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main_children_stories)
var childrenStoriesArraylist = ArrayList<ChildrenStoriesRecyclerView>()
childrenStoriesArraylist.add(ChildrenStoriesRecyclerView("Story1", R.drawable.pic1))
childrenStoriesArraylist.add(ChildrenStoriesRecyclerView("Story2", R.drawable.pic2))
childrenStoriesArraylist.add(ChildrenStoriesRecyclerView("Story3", R.drawable.pic3))
children_stories_recyclerview.layoutManager = LinearLayoutManager(this, LinearLayout.VERTICAL, false)
val childrenStoriesAdapter = ChildrenStoriesAdapter(childrenStoriesArraylist)
children_stories_recyclerview.adapter = childrenStoriesAdapter
childrenStoriesAdapter.setOnItemClickListener(object : ChildrenStoriesAdapter.ClickListener {
override fun onClick(pos: Int, aView: View) {
//The App Crash here
if (pos == 0){
my_text_view.text = "Story number 1"
my_imageview.setImageResource(R.drawable.pic1)
}else if (pos == 1){
my_text_view.text = "Story number 2"
my_imageview.setImageResource(R.drawable.pic2)
}
val intent = Intent(this#MainChildrenStories, ChildrenStoryPreview::class.java)
startActivity(intent)
}
})
}
}
MyRecyclerView Class
data class ChildrenStoriesRecyclerView(var mStoryName: String, var mStoryImage: Int)
My RecyclerView Adapter Class
class ChildrenStoriesAdapter(var myArrayList: ArrayList<ChildrenStoriesRecyclerView>) :
RecyclerView.Adapter<ChildrenStoriesAdapter.ViewHolder>() {
lateinit var mClickListener: ClickListener
fun setOnItemClickListener(aClickListener: ClickListener) {
mClickListener = aClickListener
}
override fun onCreateViewHolder(p0: ViewGroup, p1: Int): ViewHolder {
val v = LayoutInflater.from(p0.context).inflate(R.layout.children_stories_list, p0, false)
return ViewHolder(v)
}
override fun getItemCount(): Int {
return myArrayList.size
}
override fun onBindViewHolder(p0: ViewHolder, p1: Int) {
var infList = myArrayList[p1]
p0.storyName.text = infList.mStoryName
p0.storyImage.setImageResource(infList.mStoryImage)
}
inner class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView), View.OnClickListener {
override fun onClick(v: View) {
mClickListener.onClick(adapterPosition, v)
}
val storyName = itemView.findViewById(R.id.txtStoryName) as TextView
val storyImage = itemView.findViewById(R.id.imageViewChildrenStories) as ImageView
init {
itemView.setOnClickListener(this)
}
}
interface ClickListener {
fun onClick(pos: Int, aView: View)
}
}
My new Activity To show Details of the Story
class ChildrenStoryPreview : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_children_story_preview)
}
}
Pass the Event Listener to Adapter constructor also to viewholder to catch view holder (items) clicks.
class ChildrenStoriesAdapter(var myArrayList: ArrayList<ChildrenStoriesRecyclerView>
var clickListener:MyClickListener?) :
RecyclerView.Adapter<ChildrenStoriesAdapter.ViewHolder>() {
...
override fun onCreateViewHolder(p0: ViewGroup, p1: Int): ViewHolder {
val v = LayoutInflater.from(p0.context).inflate(R.layout.children_stories_list, p0, false)
return ViewHolder(v, clickListener)
}
...
inner class ViewHolder(itemView: View, clickListener:MyClickListener?) :
RecyclerView.ViewHolder(itemView) {
itemView.setOnClickListener { clickListener?.myClickedFun(...) }
...
class ChildrenStoryPreview : AppCompatActivity(), MyClickListener {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_children_story_preview)
}
override fun myClickedFun(...) {
...
}
}
Later init adapter like
..
val childrenStoriesAdapter = ChildrenStoriesAdapter(childrenStoriesArraylist, this)