'can't pass data from fragment to fragment using viewmodel.kotlin
Problem with passing data from fragment to fragment. in my application there is a button to go to the fragment on which the recycleview is located. By clicking on an item, another fragment with the description of the item should open in the recyclerview. The fragment opens, but the description remains the same, that is, the data does not change. If I do the same, but I pass data from the fragment to the new activity using the intent, everything is fine. In the fragment, I pass data through the view model. I've been struggling with this issue for a month now. I also tried to transfer data through the bundle, but the result is the same. Help. I've only been studying Kotlin for half a year.
All. I fixed the code in some places and it all worked!!!!!! Well, if there are shortcomings in the code, please write. I will add. And so this is a fully implemented data transfer in fragment
1. My Adapter
```package com.example.gardeners
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import android.widget.TextView
import androidx.recyclerview.widget.RecyclerView
class MyAdapter(private val Directorylist:ArrayList<ListItem>):RecyclerView.Adapter<MyAdapter.ViewHolder>() {
private lateinit var mListener : onItemClickListener
private var list: List<ListItem>?=null
interface onItemClickListener{
fun onItemClick(position: Int)
}
fun setOnItemClickListener(listener: onItemClickListener){
mListener = listener
}
fun getItemAt(position: Int): ListItem? {
return list?.get(position)
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val itemView = LayoutInflater.from(parent.context).inflate(R.layout.item_loyout,
parent,false)
return ViewHolder(itemView, mListener)
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val currentItem = Directorylist[position]
holder.tvTitle.text = currentItem.text_Id
holder.im.setImageResource(currentItem.imag_Id)
}
override fun getItemCount(): Int {
return Directorylist.size
}
class ViewHolder(viewItem: View, listener: onItemClickListener): RecyclerView.ViewHolder(viewItem){
val tvTitle = viewItem.findViewById<TextView>(R.id.TV)
val im = viewItem.findViewById<ImageView>(R.id.imv)
init {
itemView.setOnClickListener {
listener.onItemClick(adapterPosition)
}
}
}
}```
2. fragment 1
```package com.example.gardeners.fragments
import android.content.res.TypedArray
import android.os.Bundle
import android.view.View
import android.widget.Toast
import androidx.fragment.app.activityViewModels
import androidx.lifecycle.ViewModelProvider
import androidx.recyclerview.widget.LinearLayoutManager
import com.example.gardeners.*
import kotlinx.android.synthetic.main.fragment_directory.*
class FragmentDirectory : BaseFragment(R.layout.fragment_directory) {
private val sharedViewModel:SharedViewModel by activityViewModels()
var adapter: MyAdapter? = null
var list = ArrayList<ListItem>()
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
}
override fun onResume() {
super.onResume()
(activity as MainActivity).supportActionBar?.title = getString(R.string.strD)
list.addAll(fillArrays(resources.getStringArray(R.array.title),
getImageId(R.array.image_content), resources.getStringArray(R.array.content)))
rcView.hasFixedSize()
rcView.layoutManager = LinearLayoutManager(activity)
adapter = MyAdapter(list)
rcView. adapter = adapter
adapter?.setOnItemClickListener(object : MyAdapter.onItemClickListener{
override fun onItemClick(position: Int) {
Toast.makeText(context, "Pressed : $position", Toast.LENGTH_SHORT).show()
sharedViewModel.setSelected(list[position])
parentFragmentManager.beginTransaction()
.replace(R.id.dataContainer, TextFragment1())
.addToBackStack(null)
.commit()
}
})
}
fun fillArrays( titleArray:Array<String>, imageArray: IntArray, contentArray: Array<String>):List<ListItem>{
var listItemArray = ArrayList<ListItem>()
for (n in 0..titleArray.size -1){
var listItem = ListItem(imageArray[n], titleArray[n], contentArray[n])
listItemArray.add(listItem)
}
return listItemArray
}
fun getImageId(imageArrayId:Int): IntArray{
var tArray: TypedArray = resources.obtainTypedArray(imageArrayId)
val count = tArray.length()
val ids = IntArray(count)
for (i in ids.indices){
ids[i] = tArray.getResourceId(i, 0)
}
tArray.recycle()
return ids
}
}```
3.fragment2
```package com.example.gardeners.fragments
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import androidx.fragment.app.activityViewModels
import androidx.lifecycle.Observer
import com.example.gardeners.ListItem
import com.example.gardeners.R
import com.example.gardeners.SharedViewModel
import com.example.gardeners.databinding.FragmentText1Binding
class TextFragment1 : Fragment() {
private lateinit var binding: FragmentText1Binding
private val sharedViewModel: SharedViewModel by activityViewModels()
private lateinit var list: List<ListItem>
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
binding = FragmentText1Binding.inflate(inflater)
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
sharedViewModel.getSelected().observe(viewLifecycleOwner, Observer { ListItem ->
binding.TV.text = ListItem.text_Id
binding.imv.setImageResource(ListItem.imag_Id)
binding.textContent.text = ListItem.contentText
})
}
}```
4. viewModul
```package com.example.gardeners
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
class SharedViewModel: ViewModel() {
privat val selected= MutableLiveData<ListItem>()
fun setSelected(item: ListItem){
selected.setValue(item)
}
fun getSelected(): MutableLiveData<ListItem> {
return selected
}
}```
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|
