Kotiln: Pass Data from Adapter to Activity

Pass data from recyclerView to new activity when an item is clicked Kotlin

easiest way

in adapter class do like

class ProductAdapter(val fragment: storekotlin,private var productlist:MutableList<Product>): 
RecyclerView.Adapter<ProductAdapter.ProductViewHolder>() {

override fun onCreateViewHolder(
parent: ViewGroup,
viewType: Int
): ProductViewHolder {

val layoutView:View =
LayoutInflater.from(parent.context).inflate(R.layout.itemcard,parent,false)
return ProductViewHolder(layoutView)

}

override fun onBindViewHolder(holder: ProductViewHolder, position: Int) {

Picasso.get().load(productlist[position].prdimg).into(holder.prdimg)
holder.prdname.text = productlist[position].prdname
holder.prdprice.text = productlist[position].prdprice

holder.itemView.setOnClickListener {
val name = productlist[position].prdname
val price= productlist[position].prdprice
fragment.deatailsList(name , price) // here you can send just the position it will be more efficient
}
}

override fun getItemCount(): Int {
return productlist.size;
}

inner class ProductViewHolder(view: View): RecyclerView.ViewHolder(view){

var prdimg: ImageView = view.findViewById(R.id.prdimg)
var prdname: TextView = view.findViewById(R.id.prdname)
var prdprice: TextView = view.findViewById(R.id.prdprice)

}

in storekotlin Fragment onCreateView method pass the list and fragment like this

   val adapter = ProductAdapter(this@storekotlin,productlist)
recyclerView?.adapter = adapter

in storekotlin activity create another method

  fun deatailsList(name: String, price: String?) {

// Log.d(ContentValues.TAG, "myList:${dataList.size}")

val intent = Intent(requireContext(), DetailsActivity::class.java)

intent.putExtra("nameKey", name)
intent.putExtra("priceKey", price)

startActivity(intent)
}

in Details activity onCreate method

   val intent = intent

val rcvName = intent.getStringExtra("nameKey")
val rcvPrice= intent.getStringExtra("priceKey")

// now you can print here the selected value
textDayIncome_id.text = rcvName
textDayExpense_id.text = rcvPrice

Kotiln: pass data from adapter to activity

Method 1 :

You can use callback
First of all, define a callback in your adapter like this :

    interface CallbackInterface {   
fun passResultCallback(message: String)
}

Then initialize the callback interface in your adapter :

class YourAdapter(private val callbackInterface:CallbackInterface) :
RecyclerView.Adapter<CurrencyListAdapter.ViewHolder>() {
.
.
.
}

Then use the callback method from the interface inside your onBindViewHolder() like this :

holder.itemView.setOnClickListener {
//Set your codes about intent here
callbackInterface.passResultCallback("Your message")
}

And finally, implement your callback method in your activity like this :

class TracksActivity: AppCompatActivity(), TracksView , YourAdapterName.CallbackInterface {

private var albumsAdapter: AlbumsAdapter? = null

override fun onCreate(savedInstanceState: Bundle?, persistentState: PersistableBundle?) {
super.onCreate(savedInstanceState, persistentState)
setContentView(R.layout.activity_tracks)
}

override fun passResultCallback(message: String) {
//message is "ff"
}
}

UPDATE:

Method 2 :

If you dont use callback, as you wrote just change your activity to this :

class TracksActivity: AppCompatActivity(), TracksView {

private var albumsAdapter: AlbumsAdapter? = null

override fun onCreate(savedInstanceState: Bundle?, persistentState: PersistableBundle?) {
super.onCreate(savedInstanceState, persistentState)
setContentView(R.layout.activity_tracks)

var bundle : Bundle? = intent.extras
var message = bundle!!.getString("dd")
Log.d("dd", "${message}")
}
}

UPDATE : December 26, 2019

Method 3 : KOTLIN BASE

We can pass a fun to adapter and get data from it like this :

In our adapter :

class YourAdapter(private val clickListener: (yourData: YourData) -> Unit) :
RecyclerView.Adapter<YourAdapter.ViewHolder>() {

//YourData like String

//And we have onCreateViewHolder like this

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder = ViewHolder(
LayoutInflater.from(parent.context).inflate(R.layout.your_item, parent,false),
clickListener
)

//And we have ViewHolder class like this

inner class ViewHolder(itemView: View, private val clickListener: (yourData: YourData) -> Unit) :
RecyclerView.ViewHolder(itemView) {
.
.
.
init {
initClickListeners()
}

//And pass data here with invoke

private fun initClickListeners() {
itemView.setOnClickListener { clickListener.invoke(yourData) }
}
}

In our fragment or activity we can get data with this way :

YourAdapter { yourData ->
// we can use yourData here
}

how to pass data from adapter to fragments in kotlin via bundle?

Your code for the Adapter is alright, it seems. Firstly, whenever you have a lambda parameter, it must be set to the last of the list.

class ProductAdapter(
private val items: List<ProductResultData
private val onItemClick: (ProductResultData) -> Unit
)

// In your activity/fragment
binding.recyclerView.adapter = ProductAdapter(list) { item ->
Bundle().apply {
putParcelable("PRODUCT_ITEM", item)
}.also {
val yourFrag = YourFragment()
yourFrag.args = it
replaceFragment(yourFrag)
}
}

And make sure your ProductResultData implements Parcelable interface.

Android: pass data from RecyclerView to another Activity

var intent = Intent(activity, ClickDetail::class.java)
intent.putExtra("your_key",MainActivity.clickArray.toString())
startActivity(intent)

class ClickDetail : AppCompatActivity(){

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.traffic_click_detail)
val YourData = getIntent().getStringExtra("your_key")
}
}

How to pass data from MainActivity to Recyclerview adapter in KOTLIN ANDROID STUDIO

I had this problem today while creating an app. I searched the problem but didn't got any solution. Then I solved it by my own method as stated below.

In your MainActivity.kt, create a public function which returns the values that you want to receive in your Adapter class. I created a function getData() with a return type of HashMap in case you want to pass more than 1 values to adapter class.

fun getData(): HashMap<String, String> {
val map = HashMap<String, String>()
map["Data1"] = "Hello this is data 1"
map["Data2"] = "Hello this is data 2"

return map
}

Now, go to your adapter class and inside your onBindViewHolder function, call the function created in MainActivity.kt as shown below:

class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
val name: TextView = itemView.findViewById(R.id.name)
val description: TextView = itemView.findViewById(R.id.description)
}

override fun onBindViewHolder(holder: ViewHolder, position: Int, model: Modal) {
val activity: MainActivity? = holder.itemView.context as MainActivity
val map = activity?.getData()
val data = map?.get("Data1")
Log.d("DataFromMainActivity", data.toString())
}

Kotlin: How to pass data from SharedViewModel to Adapter

The problem you are facing is that you are trying to access the sharedViewModel from the adapter, which is not a lifecycle owner and does not have a reference to the fragment's view. A possible solution is to pass the sharedViewModel as a parameter to the adapter's constructor, and then use it in the onBindViewHolder method. For example:

// In your fragment class, initialize the sharedViewModel and the adapter
private val sharedViewModel: DeactivatedElementsViewModel by activityViewModels()
private lateinit var adapter: MyAdapter

// In your onViewCreated method, create the adapter instance and pass the sharedViewModel
adapter = MyAdapter(sharedViewModel)
recyclerView.adapter = adapter

// In your adapter class, accept the sharedViewModel as a parameter and store it as a property
class MyAdapter(private val sharedViewModel: DeactivatedElementsViewModel) : RecyclerView.Adapter<MyAdapter.ViewHolder>() {

// In your onBindViewHolder method, use the sharedViewModel to access the data
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val elementsFromStand = sharedViewModel.elementsFromStand
// Do something with the elementsFromStand
}
}

This way, you can access the sharedViewModel's data from the adapter without creating a new instance of the fragment or using detached views. However, you should also be careful about updating the data in the sharedViewModel, as it might affect other fragments that are using it. You might want to use LiveData or other observable patterns to handle data changes and notify the adapter accordingly.

Explanation:

The reason why you can't access the sharedViewModel from the adapter directly is that the adapter is not a lifecycle owner, which means it does not have a lifecycle that is tied to the fragment's view. The sharedViewModel is scoped to the activity's lifecycle, which means it can be shared by multiple fragments, but it also requires a lifecycle owner to access it. The fragment is a lifecycle owner, and it can access the sharedViewModel by using the activityViewModels() delegate, which provides the same instance of the sharedViewModel to all the fragments in the same activity. However, the adapter is not a lifecycle owner, and it does not have a reference to the fragment's view, so it can't use the activityViewModels() delegate or the viewModels() delegate (which provides a fragment-specific instance of the viewModel).

One way to solve this problem is to pass the sharedViewModel as a parameter to the adapter's constructor, and then store it as a property in the adapter class. This way, the adapter can access the sharedViewModel's data from the onBindViewHolder method, which is called when the adapter binds the data to the view holder. This approach is simple and straightforward, but it also has some drawbacks. For example, if the data in the sharedViewModel changes, the adapter might not be aware of it, and it might display outdated or inconsistent data. To avoid this, you might want to use LiveData or other observable patterns to observe the data changes in the sharedViewModel and notify the adapter to update the view accordingly. You might also want to consider the impact of updating the data in the sharedViewModel from the adapter, as it might affect other fragments that are using the same sharedViewModel. You might want to use some logic or events to coordinate the data updates and avoid conflicts or errors.

Pass data from adapter to activity using interface callback method with Kotlin

change your adapter to this

class LevelsAdaptor(private val onClick:(id:Int)->Unit) : ListAdapter<Levels, LevelsAdaptor.LevelsViewHolder>(LevelsComparator()) {

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): LevelsViewHolder {
val view: View = LayoutInflater.from(parent.context)
.inflate(R.layout.rv_storymode_items, parent, false)
return LevelsViewHolder(view)
}

override fun onBindViewHolder(holder: LevelsViewHolder, position: Int) {
val current = getItem(position)
holder.bind(
current.id,
current.mainLevel,
current.subLevel,
current.stars,
current.unlocked
)
}

inner class LevelsViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
private val btn: Button = itemView.findViewById(R.id.button)
private val rating: RatingBar = itemView.findViewById(R.id.ratingBar)
private val myContext = itemView.context
//private val myContext: Context = sumView.context
fun bind(ID: Int, ML: Int, SL: Int, Stars: Int, Unlocked: Boolean) {
btn.text = ID.toString()
btn.setTag(R.id.mainLevel, ML)
btn.setTag(R.id.subLevel, SL)
btn.setTag(R.id.visualLevel, ID)
btn.setTag(R.id.currentLevelStars, Stars)
rating.rating = Stars.toFloat()
if (Unlocked==true){btn.isEnabled=true; btn.isClickable=true}else{btn.isEnabled=false; btn.isClickable=false}
itemView.setOnClickListener {
//Set your codes about intent here
onClick(ID)
}
}
}

class LevelsComparator : DiffUtil.ItemCallback<Levels>() {
override fun areItemsTheSame(oldItem: Levels, newItem: Levels): Boolean {
return oldItem.id == newItem.id
}

override fun areContentsTheSame(oldItem: Levels, newItem: Levels): Boolean {
return oldItem == newItem
}
}
}

you initialize the adapter in your activity with

val adapter = LevelsAdaptor(){id->
//TODO do something with id passed from adapter, e.g. create new fragment
}

I would also recommend using Jetpack Navigation you could use the detail view as entering the level

How to send a variable to an Adapter to send it through an Intent to another activity?

Firstly, create a MyAdapter constructor where you pass arrayList as well as pedidoId like, your MyAdapter should be something like below:

MyAdapter.class

class MyAdapter(private val platoList : ArrayList<Plato>, val pedidoId:String
) : RecyclerView.Adapter<MyAdapter.MyViewHolder>() {
........
.....
....

//in your bind(..) method
fun bind(plato: Plato){
platoTouch.setOnClickListener{
intent.putExtra("id", platoName.text.toString())
intent.putExtra("pedidoId", pedidoId)
mActivity.startActivity(intent)
}
}
}

And, in your MenuAtipicoActivity you need to do something like:

MenuAtipicoActivity

class MenuAtipicoActivity : AppCompatActivity() {
...............
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_menu_atipico)

recyclerView = findViewById(R.id.recyclerView)
recyclerView.layoutManager = LinearLayoutManager(this)
recyclerView.setHasFixedSize(true)

platoArrayList = arrayListOf()
pedidoId = intent.extras?.getString("pedidoId") //This is the variable I need to send
myAdapter = MyAdapter(platoArrayList,pedidoId)
recyclerView.adapter = myAdapter
EventChangeListener()

Setup()

}
..........
........

}


Related Topics



Leave a reply



Submit