Reputation: 2255
I customize a RecyclerView class which will display the content of val backupItemList: List<MSetting>
in Kotlin in Code B
Now I modify the data of backupItemList outside RecyclerView class, I think the Code D will display the latest data in UI, but I failed, the UI is still to display old data. I have to use Code C to display the latest data.
What's wrong with the Code D?
Code A
class UIMain : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.layout_main)
allList= SettingHandler().getListAllSetting()
mRecyclerView.layoutManager = LinearLayoutManager(this, LinearLayout.VERTICAL, false)
mCustomAdapter= CustomAdapter(allList)
mRecyclerView.adapter= mCustomAdapter
}
public override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent) {
//Code C
if (resultCode == RESULT_OK) {
allList=SettingHandler().getListAllSetting()
mCustomAdapter= CustomAdapter(allList)
mRecyclerView.adapter= mCustomAdapter
mCustomAdapter.notifyDataSetChanged()
mCustomAdapter.setSelectedItem(selectedBackupItem)
}
//Code D
if (resultCode == RESULT_OK) {
allList=SettingHandler().getListAllSetting()
mCustomAdapter.setSelectedItem(selectedBackupItem)
}
}
}
Code B
class CustomAdapter (val backupItemList: List<MSetting>) : RecyclerView.Adapter<CustomAdapter.ViewHolder>() {
val noRecord=-1
private var mSelectedItem = noRecord
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): CustomAdapter.ViewHolder {
val v = LayoutInflater.from(parent.context).inflate(R.layout.item_recyclerview, parent, false)
return ViewHolder(v)
}
fun getSelectedItem():Int{
return mSelectedItem
}
fun setSelectedItem(index:Int){
if (index in 0..(backupItemList.size-1) ){
mSelectedItem=index
notifyDataSetChanged();
}
}
override fun onBindViewHolder(holder: CustomAdapter.ViewHolder, position: Int) {
holder.bindItems(backupItemList[position])
}
override fun getItemCount(): Int {
return backupItemList.size
}
inner class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
fun bindItems(aMSetting: MSetting) {
itemView.tvSubject.text=aMSetting.name
itemView.tvCreatedDate.text=aMSetting.createdDate.toDateString()
itemView.tvDescription.text=aMSetting.description
itemView.radioButton.setOnClickListener {
mSelectedItem=adapterPosition
notifyDataSetChanged();
}
if(adapterPosition == 0 && mSelectedItem == noRecord) {
itemView.radioButton.isChecked = true
mSelectedItem=adapterPosition
}
else {
itemView.radioButton.isChecked =(adapterPosition == mSelectedItem)
}
}
}
}
To civic.LiLister:
Both Code C And Code D get the same result if I use Code E (I replace val with var),why?
Code E
class CustomAdapter (var backupItemList: List<MSetting>) : RecyclerView.Adapter<CustomAdapter.ViewHolder>() {
val noRecord=-1
private var mSelectedItem = noRecord
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): CustomAdapter.ViewHolder {
val v = LayoutInflater.from(parent.context).inflate(R.layout.item_recyclerview, parent, false)
return ViewHolder(v)
}
fun getSelectedItem():Int{
return mSelectedItem
}
fun setSelectedItem(index:Int){
if (index in 0..(backupItemList.size-1) ){
mSelectedItem=index
notifyDataSetChanged();
}
}
override fun onBindViewHolder(holder: CustomAdapter.ViewHolder, position: Int) {
holder.bindItems(backupItemList[position])
}
override fun getItemCount(): Int {
return backupItemList.size
}
inner class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
fun bindItems(aMSetting: MSetting) {
itemView.tvSubject.text=aMSetting.name
itemView.tvCreatedDate.text=aMSetting.createdDate.toDateString()
itemView.tvDescription.text=aMSetting.description
itemView.radioButton.setOnClickListener {
mSelectedItem=adapterPosition
notifyDataSetChanged();
}
if(adapterPosition == 0 && mSelectedItem == noRecord) {
itemView.radioButton.isChecked = true
mSelectedItem=adapterPosition
}
else {
itemView.radioButton.isChecked =(adapterPosition == mSelectedItem)
}
}
}
}
Upvotes: 8
Views: 11388
Reputation: 6981
In your Activity onCreate method
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.layout_main)
allList = ArrayList< MSetting>()
mCustomAdapter = CustomAdapter(mChildList)
mRecyclerView.layoutManager = LinearLayoutManager(context)
mRecyclerView.adapter = mCustomAdapter
}
Now in onActivityResult
public override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent) {
//Code C
if (resultCode == RESULT_OK) {
if(data != null){
allList.clear()
allList.addAll(SettingHandler().getListAllSetting())
mCustomAdapter.notifyDataSetChanged()
mCustomAdapter.setSelectedItem(selectedBackupItem)
}
}
}
Upvotes: 6
Reputation: 2197
The secret maybe hide here:
class CustomAdapter (val backupItemList: List)
When you init an instance of CustomAdapter, the value is copied to property backupItemList, rather than assigned the reference. Therefore, when you change property allList of UIMain, the backupItemList won't change as you expected.
The solution is simple, as Ganesh Tikone wrote: add an method to update backupItemList.
fun updateData(data: List<MovieModel>) {
backupItemList.clear()
backupItemList.addAll(data)
notifyDataSetChanged()
}
and change Code D to:
//Code D
if (resultCode == RESULT_OK) {
allList=SettingHandler().getListAllSetting()
mCustomAdapter.updateData(allList)
mCustomAdapter.setSelectedItem(selectedBackupItem)
}
Have a try.
Upvotes: 7
Reputation: 1057
private var adapter: RecentMovieAdapter? = null
Adapter is initialized in onCreateView method of fragment
adapter = RecentMovieAdapter(activity, this)
This is callback method in Fragment, which gets data from Server using Threading technique
override fun onDataReceived(randomDialog: List<MovieModel>) {
shimmerView!!.stopShimmerAnimation()
shimmerView!!.visibility = View.GONE
adapter!!.updateData(randomDialog)
}
private var movieList: MutableList<MovieModel> = mutableListOf<MovieModel>()
Add update function in Adapter class like this
fun updateData(data: List<MovieModel>) {
movieList.clear()
movieList.addAll(data)
notifyDataSetChanged()
}
Upvotes: 2
Reputation: 555
In your code D, you are overwriting the reference for allList.
And the backupItemList in CustomAdapter has the reference for the same. So if you reassign the reference for allList the changes will not be picked up in recycler view
first make sure allList is mutable
val allList = mutableListOf<MSetting>()
then in code D
allList.clear()
allList.addAll(SettingHandler().getListAllSetting())
mCustomAdapter.notifyDataSetChanged()
Upvotes: 3
Reputation: 12953
The problem is you are not using any binding
which means when you modify list
, Adapter
won't be aware of that hence it simply displays old items, but once you notify adapter
about changes in your list using notifyDatasetChanged
, it will try to refresh items with new data. If you want to achieve functionality with code D
, you need to use Data Binding using Observable pattern.For more information RecyclerView and Data Binding
Upvotes: 2
Reputation: 7944
Check this code,
if (resultCode == RESULT_OK) {
allList.clear()
allList=SettingHandler().getListAllSetting()
mCustomAdapter= CustomAdapter(allList)
mRecyclerView.adapter= mCustomAdapter
mCustomAdapter.setSelectedItem(selectedBackupItem)
}
Upvotes: 2