I had one learning project that require RecyclerView item to send his detailed data to another activity with getParcelableExtra, my problem is when I clicked the item, the data is null on detailsActivity then I check it with the log.d, and yes it’s null. any solution ;
here’s the code main activity
class MainMyRecyclerViewActivity : AppCompatActivity() {
private lateinit var binding: ActivityMyrecyclerviewMainBinding
private lateinit var rvHeroes: RecyclerView
private val list = ArrayList<Hero>()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMyrecyclerviewMainBinding.inflate(layoutInflater)
setContentView(binding.root)
rvHeroes = binding.rvMymainRv
rvHeroes.setHasFixedSize(true)
list.addAll(listHeroes)
showRecyclerList()
}
private fun showRecyclerList() {
//on change orientation adapter behavior
if (applicationContext.resources.configuration.orientation == Configuration.ORIENTATION_LANDSCAPE) {
rvHeroes.layoutManager = GridLayoutManager(this, 2)
} else {
rvHeroes.layoutManager = LinearLayoutManager(this)
}
val listHeroAdapter = ListHeroAdapter(list)
rvHeroes.adapter = listHeroAdapter
listHeroAdapter.setOnItemClickCallBack(object : OnItemClickCallback {
override fun onItemClicked(data: Hero) {
showSelectedHero(data)
sendIntent(data)
}
})
}
private fun sendIntent(dataHero: Hero) {
val intent = Intent(this@MainMyRecyclerViewActivity, DetailsActivity::class.java)
intent.putExtra("DATA", dataHero.photo)
intent.putExtra("DATA", dataHero.name)
intent.putExtra("DATA", dataHero.description)
startActivity(intent)
}
private val listHeroes: ArrayList<Hero>
get() {
val dataName = resources.getStringArray(R.array.data_name)
val description = resources.getStringArray(R.array.data_description)
val dataPhoto = resources.obtainTypedArray(R.array.data_photo)
val listHero = ArrayList<Hero>()
for (i in dataName.indices) {
val hero = Hero(dataName[i], description[i], dataPhoto.getResourceId(i, -1))
listHero.add(hero)
}
return listHero
}
private fun showSelectedHero(hero: Hero) {
Toast.makeText(this, "you selected ${hero.name}", Toast.LENGTH_SHORT).show()
}
}
here’s the adapter
class ListHeroAdapter(private val listHero: ArrayList<Hero>) :
RecyclerView.Adapter<ListViewHolder>() {
private lateinit var onItemClickCallback: OnItemClickCallback
fun setOnItemClickCallBack(onItemClickCallback: OnItemClickCallback) {
this.onItemClickCallback = onItemClickCallback
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ListViewHolder {
val view: View =
LayoutInflater.from(parent.context).inflate(R.layout.item_myrecyclerview, parent, false)
return ListViewHolder(view)
}
override fun onBindViewHolder(holder: ListViewHolder, position: Int) {
val (name, description, photo) = listHero[position]
holder.imgPhoto.setImageResource(photo)
holder.tvName.text = name
holder.tvDescription.text = description
holder.itemView.setOnClickListener {
onItemClickCallback.onItemClicked(listHero[holder.adapterPosition])
}
}
override fun getItemCount(): Int = listHero.size
}
this the target activity
class DetailsActivity : AppCompatActivity() {
private lateinit var binding: ActivityDetailsBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityDetailsBinding.inflate(layoutInflater)
setContentView(binding.root)
val data = intent.getParcelableExtra<Hero>("DATA")
binding.tvDetailsNameHero.text = data?.name
binding.tvDetailsDeskription.text = data?.description
data?.photo?.let { binding.ivDetails.setImageResource(it) }
Log.d("details data", data?.name.toString())
}
}
here’s is data class I’ve using
@kotlinx.parcelize.Parcelize
data class Hero(
var name: String,
var description: String,
var photo: Int
) : Parcelable
the interface
interface OnItemClickCallback {
fun onItemClicked(data: Hero)
}
any suggestion will be good for me, thank you.
3
Answers
The problem is here
You are sending single item in your intent as a String with the same key name
The first solution would be you need to send your class object
And
the second solution should send all extra parameters with different key names
instead of this
and receive data like this in your details activity
I think you’re problem is here.
What you’re doing here is putting the value of
dataHero.photo
into the Bundle with the keyDATA
. Then you’re overwriting that withdataHero.name
, and then again withdataHero.description
.You can see from the image below that there are a lot of overloaded methods that use the same name but assign a different type.
So you are able to assign almost any value to a particular key (
DATA
), and the reason the call to retrieve the Parcelable is null, is because the value ofDATA
in the end is not a Parcelable implementation. The last assignment was of type String, which does not implement the Parcelable interface.As mentioned by @AskNilesh use
intent.putExtra("DATA", dataHero)
instead.Change sendIntent method to this: