当 Kotlin 中的数据发生变化时,如何在 RecyclerView 中重新绑定项目?
Posted
技术标签:
【中文标题】当 Kotlin 中的数据发生变化时,如何在 RecyclerView 中重新绑定项目?【英文标题】:How to rebind item in RecyclerView when the data changed in Kotlin? 【发布时间】:2018-09-13 15:36:30 【问题描述】:我自定义了一个 RecyclerView 类,它将在代码 B 的 Kotlin 中显示 val backupItemList: List<MSetting>
的内容
现在我在RecyclerView类外面修改backupItemList的数据,我认为Code D会在UI中显示最新的数据,但是我失败了,UI仍然是显示旧的数据。 我必须使用 Code C 来显示最新数据。
代码 D 有什么问题?
代码 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)
代码 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)
致 civic.LiLister:
如果我使用代码 E(我将 val 替换为 var),代码 C 和代码 D 都会得到相同的结果,为什么?
代码 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)
【问题讨论】:
请明确您的观点,您在哪里更改来自服务器的数据? 从 UI,我通过 UI 编辑 allList 来自另一个活动? 是的。从另一个活动,我使用public override fun onActivityResult
来处理结果
清除一个点,您想在列表中添加更多项目还是编辑之前添加的项目?
【参考方案1】:
秘密可能隐藏在这里:
类 CustomAdapter (val backupItemList: List)
当您初始化 CustomAdapter 的实例时,该值被复制到属性 backupItemList,而不是分配引用。因此,当您更改 UIMain 的 allList 属性时,backupItemList 不会像您预期的那样发生变化。
解决方案很简单,正如 Ganesh Tikone 所写:添加一个方法来更新 backupItemList。
fun updateData(data: List<MovieModel>)
backupItemList.clear()
backupItemList.addAll(data)
notifyDataSetChanged()
并将代码 D 更改为:
//Code D
if (resultCode == RESULT_OK)
allList=SettingHandler().getListAllSetting()
mCustomAdapter.updateData(allList)
mCustomAdapter.setSelectedItem(selectedBackupItem)
试一试。
【讨论】:
谢谢!请看我修改后的问题,当我使用class CustomAdapter (var backupItemList: List)
时,代码 C 和代码 D 得到相同的结果@
当我初始化一个CustomAdapter (var backupItemList: List)
的实例时,我认为会为backupItemList分配一个引用,对吧?
还有,allList 是 List在您的 Activity onCreate 方法中
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
现在在 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)
【讨论】:
【参考方案3】:在您的代码 D 中,您覆盖了 allList 的引用。
CustomAdapter 中的 backupItemList 也有相同的参考。 因此,如果您重新分配 allList 的引用,则不会在回收站视图中获取更改
首先确保 allList 是可变的
val allList = mutableListOf<MSetting>()
然后在代码 D 中
allList.clear()
allList.addAll(SettingHandler().getListAllSetting())
mCustomAdapter.notifyDataSetChanged()
【讨论】:
【参考方案4】:检查此代码,
if (resultCode == RESULT_OK)
allList.clear()
allList=SettingHandler().getListAllSetting()
mCustomAdapter= CustomAdapter(allList)
mRecyclerView.adapter= mCustomAdapter
mCustomAdapter.setSelectedItem(selectedBackupItem)
【讨论】:
记得在onActivityResult()
的日志中查看你的列表是否有数据。
谢谢!但是您的代码就像我的代码 C,我认为也许有更好的方法
我认为你不需要运行allList.clear()
,因为allList=SettingHandler().getListAllSetting()
会自动清除旧数据
onActivityResult() 是否返回 RESULT_OK?
如果我在另一个活动中成功编辑了一条记录,我将分配RESULT_OK并将其返回给主活动【参考方案5】:
问题是你没有使用任何binding
,这意味着当你修改list
时,Adapter
不会意识到这一点,因此它只是显示旧项目,但是一旦你通知adapter
关于更改您的列表使用notifyDatasetChanged
,它将尝试使用新数据刷新项目。如果你想用code D
实现功能,你需要使用Data Binding using Observable pattern。更多信息RecyclerView and Data Binding
【讨论】:
我认为代码notifyDataSetChanged();
应该重新绑定基于修改过的allList的items,但实际上系统并没有这样做
还有更多,您能否向我展示一些示例代码,以使用关于我的问题的 Observable 模式使用数据绑定?【参考方案6】:
片段代码
private var adapter: RecentMovieAdapter? = null
Adapter在fragment的onCreateView方法中初始化
adapter = RecentMovieAdapter(activity, this)
这是Fragment中的回调方法,使用线程技术从Server获取数据
override fun onDataReceived(randomDialog: List<MovieModel>)
shimmerView!!.stopShimmerAnimation()
shimmerView!!.visibility = View.GONE
adapter!!.updateData(randomDialog)
适配器类代码
private var movieList: MutableList<MovieModel> = mutableListOf<MovieModel>()
像这样在Adapter类中添加更新函数
fun updateData(data: List<MovieModel>)
movieList.clear()
movieList.addAll(data)
notifyDataSetChanged()
【讨论】:
【参考方案7】:yourAdapter().notifyDataSetChanged
【讨论】:
以上是关于当 Kotlin 中的数据发生变化时,如何在 RecyclerView 中重新绑定项目?的主要内容,如果未能解决你的问题,请参考以下文章
当 Extjs 中的窗口大小发生变化时如何显示“分页工具栏”?
当AngularJS网站中的网站内容发生变化时,如何使index.html不缓存?