web-dev-qa-db-fra.com

Comment relier un élément dans RecyclerView lorsque les données sont modifiées dans Kotlin?

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)
            }       
            }

        }

    }
6
HelloCW

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.

4
civic.LiLister

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) 
              } 
           }

      }        
4
Shweta Chauhan

Vérifiez ce code, 

if (resultCode == RESULT_OK) {
           allList.clear()
           allList=SettingHandler().getListAllSetting()
           mCustomAdapter= CustomAdapter(allList)
           mRecyclerView.adapter= mCustomAdapter  
           mCustomAdapter.setSelectedItem(selectedBackupItem) 
       }
2
farhana

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

2
rajan ks

Code de fragment

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)
}

Code de classe d'adaptateur

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()
}
2
Ganesh Tikone

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()
2
AbdulAli

votreAdapter (). notifyDataSetChanged

0
trinadh thatakula