Je personnalise une classe RecyclerView qui affiche le contenu de val backupItemList: List<MSetting>
dans Kotlin dans le code B
Maintenant, je modifie les données de backupItemList en dehors de la classe RecyclerView, je pense que le code D affichera les dernières données dans l'interface utilisateur, mais j'ai échoué, l'interface utilisateur doit toujours afficher les anciennes données . Je dois utiliser le code C pour afficher les dernières Les données.
Quel est le problème avec le 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)
}
}
}
}
À civic.LiLister:
Le code C et le code D obtiennent le même résultat si j'utilise le code E (je remplace val par var), pourquoi
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)
}
}
}
}
Le secret peut-être cacher ici:
class CustomAdapter (val backupItemList: List)
Lorsque vous initiez une instance de CustomAdapter, la valeur est copiée dans la propriété backupItemList, au lieu d'être affectée à la référence. Par conséquent, lorsque vous modifiez la propriété allList de UIMain, la sauvegardeItemList ne changera pas comme prévu.
La solution est simple, écrit Ganesh Tikone: ajoutez une méthode pour mettre à jour backupItemList.
fun updateData(data: List<MovieModel>) {
backupItemList.clear()
backupItemList.addAll(data)
notifyDataSetChanged()
}
et remplacez le code D par:
//Code D
if (resultCode == RESULT_OK) {
allList=SettingHandler().getListAllSetting()
mCustomAdapter.updateData(allList)
mCustomAdapter.setSelectedItem(selectedBackupItem)
}
Essaye.
Dans votre méthode 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
}
> 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)
}
}
}
Vérifiez ce code,
if (resultCode == RESULT_OK) {
allList.clear()
allList=SettingHandler().getListAllSetting()
mCustomAdapter= CustomAdapter(allList)
mRecyclerView.adapter= mCustomAdapter
mCustomAdapter.setSelectedItem(selectedBackupItem)
}
Le problème est que vous n'utilisez aucune variable binding
, ce qui signifie que lorsque vous modifiez list
, Adapter
ne sera pas conscient de ce fait, il affichera simplement les anciens éléments, mais une fois que vous aurez informé adapter
des modifications apportées à votre liste à l'aide de notifyDatasetChanged
, il tentera d'actualiser les éléments. avec de nouvelles données. Si vous souhaitez utiliser la fonctionnalité code D
, vous devez utiliser la liaison de données à l'aide du modèle Observable.Pour plus d'informations RecyclerView et liaison de données
private var adapter: RecentMovieAdapter? = null
L'adaptateur est initialisé dans la méthode onCreateView de fragment
adapter = RecentMovieAdapter(activity, this)
C'est la méthode de rappel dans Fragment, qui récupère les données du serveur à l'aide de la technique de threading
override fun onDataReceived(randomDialog: List<MovieModel>) {
shimmerView!!.stopShimmerAnimation()
shimmerView!!.visibility = View.GONE
adapter!!.updateData(randomDialog)
}
private var movieList: MutableList<MovieModel> = mutableListOf<MovieModel>()
Ajouter une fonction de mise à jour dans la classe Adapter comme ceci
fun updateData(data: List<MovieModel>) {
movieList.clear()
movieList.addAll(data)
notifyDataSetChanged()
}
Dans votre code D, vous écrasez écrasez la référence for allList.
Et backupItemList dans CustomAdapter a la référence pour le même . Ainsi, si vous réaffectez la référence à allList, les modifications ne seront pas collectées dans la vue Recycler.
d'abord assurez-vous que allList est mutable
val allList = mutableListOf<MSetting>()
puis dans le code D
allList.clear()
allList.addAll(SettingHandler().getListAllSetting())
mCustomAdapter.notifyDataSetChanged()
votreAdapter (). notifyDataSetChanged