I want to store Shared Preferences of a Button in a Recycler View Adapter that is used by Fragment.
class RecyclerViewAdapter : RecyclerView.Adapter<RecyclerViewAdapter.ViewHolder>() {
private val name = arrayOf("Android Dev W1",
"Android Dev W2", "Web Dev W1", "Learn Kotlin B1",
"Android Dev W3", "Android Dev W4", "Web Dev W2",
"Learn DSA")
private val date = arrayOf("20:00 18th May, 2021", "04:00 18th May, 2021",
"07:00 19th May, 2021", "04:00 20th May, 2021",
"01:00 21th May, 2021", "10:00 21th May, 2021",
"20:00 27th May, 2021", "10:00 30th May, 2021")
private val btn = arrayOf(false, false, false, false, false, false, false, false)
inner class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
var itemName: TextView = itemView.findViewById(R.id.workshopName)
var itemDate: TextView = itemView.findViewById(R.id.workshopDate)
var button: Button = itemView.findViewById(R.id.applyBtn)
val prefs = itemView.context.getSharedPreferences("prefs", MODE_PRIVATE)
init {
for(i in 0 .. 7) {
//checking via sharedPreferences if this app is being run first time or not
btn[i] = prefs.getBoolean("registered$i", false)
if (btn[i]) {
hideButton()
} else {
showButton()
}
}
}
fun hideButton() {
button.text = "Applied"
button.isClickable = false
button.setBackgroundColor(Color.parseColor("#FF3700E9"))
}
private fun showButton() {
button.text = "Apply"
button.isClickable = true
button.setBackgroundColor(Color.parseColor("#FF6200EE"))
}
}
override fun onCreateViewHolder(viewGroup: ViewGroup, i: Int): ViewHolder {
val v = LayoutInflater.from(viewGroup.context)
.inflate(R.layout.frame_textview, viewGroup, false)
return ViewHolder(v)
}
override fun onBindViewHolder(viewHolder: ViewHolder, i: Int) {
viewHolder.itemName.text = name[i]
viewHolder.itemDate.text = date[i]
viewHolder.button.setOnClickListener {
viewHolder.prefs.edit().putBoolean("registered$i", true).apply()
btn[i] = true
viewHolder.hideButton()
}
}
override fun getItemCount(): Int {
return name.size
}
}
The fragment that is using this adapter
class AvailableWorkshops : Fragment() {
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_available_workshops, container, false)
}
override fun onViewCreated(itemView: View, savedInstanceState: Bundle?) {
super.onViewCreated(itemView, savedInstanceState)
val recyclerView = itemView.findViewById<RecyclerView>(R.id.recycler_view)
recyclerView.apply {
// set a LinearLayoutManager to handle Android
// RecyclerView behavior
layoutManager = LinearLayoutManager(activity)
// set the custom adapter to the RecyclerView
adapter = RecyclerViewAdapter()
}
}
}
For example, there are 8 item in this adapter and I click on 5th item it will call onClickListener() and change button property that is completely fine.
But, when we restart the app is changes back to default button properties(Shared Preference is not working)
Again, If I click on every item and restart the app , It will now show new changes on every item(Shared Preference is working here).
I want to store that if I click on 5th Item, then on app restart it should change display of only 5th item, not for every item.
I want to store that if I click on 5th Item, then on app restart it should change display of only 5th item, not for every item.
Your Problem
A ViewHolder
represents one item in the RecyclerView
. When you initialize your ViewHolder
you apply the preference 7 times to the same button.
inner class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
//...
init {
// ** THIS IS NOT HIDING OR SHOWING SEVEN DIFFERENT BUTTONS - THIS IS HIDING OR
// SHOWING THIS VIEWHOLDER'S ONE BUTTON SEVEN TIMES **
for(i in 0 .. 7) {
//checking via sharedPreferences if this app is being run first time or not
btn[i] = prefs.getBoolean("registered$i", false)
if (btn[i]) {
hideButton()
} else {
showButton()
}
}
}
A Solution
Delete your init
block in the ViewHolder
and move your hide / show logic to the onBindViewHolder
method where you set up each single instance.
override fun onBindViewHolder(viewHolder: ViewHolder, i: Int) {
viewHolder.itemName.text = name[i]
viewHolder.itemDate.text = date[i]
// ** SHOW OR HIDE THIS INSTANCE'S BUTTON - AND ONLY THIS INSTANCE'S BUTTON **
if (viewHolder.prefs.getBoolean("registered$i", false)) {
viewHolder.hideButton()
} else {
viewHolder.showButton()
}
viewHolder.button.setOnClickListener {
viewHolder.prefs.edit().putBoolean("registered$i", true).apply()
btn[i] = true
viewHolder.hideButton()
}
}