Reputation: 117
I have a RecyclerView that contains a list of views with EditText fields in them.
I want to be able to change the value in the EditTexts and have that update my dataset. I seem to be accomplishing this but when I add a new item to the list, the values in the EditTexts get mixed up.
I cannot find why this is happening. Any thoughts?
Main Activity
class MainActivity : AppCompatActivity() {
private lateinit var recyclerView: RecyclerView
private lateinit var viewAdapter: RecyclerView.Adapter<*>
private lateinit var viewManager: RecyclerView.LayoutManager
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val myDataSet = ArrayList<Person>()
myDataSet.add(Person("Tommy"))
myDataSet.add(Person("John"))
myDataSet.add(Person("Suzie"))
myDataSet.add(Person("Leslie"))
viewManager = LinearLayoutManager(this)
viewAdapter = PersonAdapter(myDataSet)
recyclerView = findViewById<RecyclerView>(R.id.rvPersons).apply {
setHasFixedSize(true)
layoutManager = viewManager
adapter = viewAdapter
}
val button = findViewById<Button>(R.id.myButton)
button.setOnClickListener {
myDataSet.add(Person("new person"))
myDataSet.forEach {person ->
Log.i("my-tag", person.name)
}
rvPersons.adapter?.notifyDataSetChanged()
}
}
}
People Adapter
class PersonAdapter(private val myDataSet: ArrayList<Person>) :
RecyclerView.Adapter<PersonAdapter.MyViewHolder>() {
class MyViewHolder(view: View) : RecyclerView.ViewHolder(view) {
val editText: EditText = view.my_edittext
var textView: TextView = view.my_textView
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {
return MyViewHolder(
LayoutInflater.from(parent.context)
.inflate(R.layout.item_person, parent, false)
)
}
override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
holder.editText.setText(myDataSet[position].name)
holder.editText.doAfterTextChanged { text ->
if (!text.isNullOrBlank()) {
myDataSet[position].name = text.toString()
}
}
holder.textView.text = myDataSet[position].name
}
override fun getItemCount(): Int = myDataSet.size
}
Upvotes: 2
Views: 5145
Reputation: 81
For Recycler view Recycle issues :- Add This
@Override
public int getItemViewType(int position) {
return position;
}
@Override
public long getItemId(int position) {
return position;
}
Upvotes: 7
Reputation: 219
You have to call this.notifyDataSetChanged();
after adding new text into editText.
Upvotes: 0
Reputation: 2651
Since old TextWachers are all left registered over onBindViewHolder calls, data is to be broken. Retain the reference to the TextWatcher in MyViewHolder and remove it first in onBindViewHolder().
class PersonAdapter(private val myDataSet: ArrayList<Person>) :
RecyclerView.Adapter<PersonAdapter.MyViewHolder>() {
class MyViewHolder(view: View) : RecyclerView.ViewHolder(view) {
val editText: EditText = view.my_edittext
var textView: TextView = view.my_textView
var watcher: TextWatcher? = null
}
override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
holder.editText.removeTextChangedListener(holder.watcher)
holder.editText.setText(myDataSet[position].name)
holder.watcher = holder.editText.doAfterTextChanged { text ->
if (!text.isNullOrBlank()) {
myDataSet[position].name = text.toString()
}
}
holder.textView.text = myDataSet[position].name
}
:
}
Upvotes: 4