web-dev-qa-db-ja.com

Kotlinでデータが変更されたときにRecyclerViewでアイテムを再バインドする方法

コードBのKotlinでval backupItemList: List<MSetting>のコンテンツを表示するRecyclerViewクラスをカスタマイズします

今、RecyclerViewクラスの外でbackupItemListのデータを変更します。コード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)
            }       
            }

        }

    }
7
HelloCW

その秘密は多分ここに隠れるでしょう:

クラス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)                
   }  

やってみてください。

6
civic.LiLister

アクティビティの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

あなたのコードDでは、あなたは参照を上書き for allListです。

また、CustomAdapterのbackupItemListには、同じものへの参照があります。したがって、allListの参照を再割り当てした場合、変更はリサイクラービューで取得されません。

最初にallListが変更可能であることを確認します

val allList = mutableListOf<MSetting>()

次にコードDで

allList.clear()
allList.addAll(SettingHandler().getListAllSetting())
mCustomAdapter.notifyDataSetChanged()
3
AbdulAli

このコードをチェックして、

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

問題は、bindingを使用していないことです。つまり、listを変更すると、Adapterはそれを認識しないため、古いアイテムを表示するだけですが、通知するとadapternotifyDatasetChangedを使用したリストの変更については、新しいデータでアイテムを更新しようとします。 code Dで機能を実現したい場合は、Observableパターンを使用したデータバインディングを使用する必要があります。詳細については RecyclerViewとデータバインディング

2
rajan ks

フラグメントコード

private var adapter: RecentMovieAdapter? = null

アダプターはフラグメントのonCreateViewメソッドで初期化されます

adapter = RecentMovieAdapter(activity, this)

これはFragmentのコールバックメソッドであり、スレッド手法を使用してサーバーからデータを取得します。

override fun onDataReceived(randomDialog: List<MovieModel>) {
    shimmerView!!.stopShimmerAnimation()
    shimmerView!!.visibility = View.GONE
    adapter!!.updateData(randomDialog)
}

アダプタクラスコード

private var movieList: MutableList<MovieModel> = mutableListOf<MovieModel>()

このようにアダプタクラスに更新機能を追加

fun updateData(data: List<MovieModel>) {
    movieList.clear()
    movieList.addAll(data)
    notifyDataSetChanged()
}
2
Ganesh Tikone

yourAdapter()。notifyDataSetChanged

0