Все дочерние элементы RecyclerView изменяются при изменении одного дочернего элемента recyclerview при нажатии на элемент

#android #kotlin #lambda #android-recyclerview #nestedrecyclerview

#Android #kotlin #лямбда #android-recyclerview #вложенный recyclerview

Вопрос:

Я работаю с вложенным RecyclerView. Согласно бизнес-логике, сначала я должен вызвать API, который извлекает список элементов, отображаемых в представлении родительского ресайклера. После этого, если пользователь щелкает по любому из элементов родительского представления recycler, вызывается другой API, который извлекает список подпунктов, и я должен показать список элементов во внутреннем представлении recycler этого родительского представления recycler с нажатой позицией.

Я успешно реализовал отображение элементов в родительском представлении recycler и подпунктов во вложенном представлении recycler с нажатой позицией.

Но проблема, с которой я сталкиваюсь, заключается в том, что когда я нажимаю на какой-либо конкретный элемент родительского представления recycler, все остальные элементы вложенного представления recycler изменяются на вновь заполненные значения подпунктов.

Как я могу решить эту проблему?. Вот пример кода

main_item.xml

 <?xml version="1.0" encoding="utf-8"?>

<androidx.appcompat.widget.LinearLayoutCompat xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical">

    <com.google.android.material.card.MaterialCardView
        style="@style/CardViewStyle"
        android:id="@ id/chapter_layout"
        android:layout_width="match_parent">

            <com.google.android.material.textview.MaterialTextView
                android:id="@ id/chapter_name_text_view"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"/>

            <com.google.android.material.textview.MaterialTextView
                android:id="@ id/header_text_view"
                android:layout_width="0dp"
                android:layout_height="wrap_content"/>   

    </com.google.android.material.card.MaterialCardView>

    <androidx.recyclerview.widget.RecyclerView
        android:id="@ id/chapter_topic_recycler_view"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:visibility="gone"
        app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
        tools:itemCount="3"
        tools:listitem="@layout/item_main" />

</androidx.appcompat.widget.LinearLayoutCompat>
  

MainItemViewHolder.kt

 class MainItemViewHolder(val view: View) :  RecyclerView.ViewHolder(view) {

    fun bind(item: SpecificChapter, onClick: (SpecificChapter, Int) -> Unit) {
        with(view) {
            chapter_name_text_view.text = "Chapter "  item.no
            header_text_view.text = item.name

            chapter_layout.setOnClickListener { onClick(item, bindingAdapterPosition) }
        }
    }
}
  

MainItemAdapter.kt

 class MainItemAdapter(
    val onClick: (SpecificChapter, Int) -> Unit
) : ListAdapter<SpecificChapter, MainItemViewHolder>(DIFF_CALLBACK) {

    companion object {
        private val DIFF_CALLBACK = object : DiffUtil.ItemCallback<SpecificChapter>() {
            override fun areItemsTheSame(old: SpecificChapter, aNew: SpecificChapter) = (old.id == aNew.id)
            override fun areContentsTheSame(old: SpecificChapter, aNew: SpecificChapter) = (old == aNew)
        }
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MainItemViewHolder {
        return MainItemViewHolder(parent.inflate(R.layout.main_item))
    }

    override fun onBindViewHolder(holder: MainItemViewHolder, position: Int) {
        holder.bind(getItem(position)!!, onClick)
    }

}
  

sub_item.xml

 <?xml version="1.0" encoding="utf-8"?>

<com.google.android.material.card.MaterialCardView
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

        <com.google.android.material.textview.MaterialTextView
            android:id="@ id/chapter_topic_text_view"
            android:layout_width="0dp"
            android:layout_height="wrap_content" />

</com.google.android.material.card.MaterialCardView>
  

SubItemViewHolder.kt

 class SubItemViewHolder(val view: View) : RecyclerView.ViewHolder(view) {

    fun bind(item: SpecificTopic, onClick: (SpecificTopic) -> Unit) {
        with(view) {
            chapter_topic_text_view.text = item.name
            chapter_topic_layout.setOnClickListener { onClick(item) }
        }
    }
}
  

SubItemAdapter.kt

 class SubItemAdapter(
    val onClick: (SpecificTopic) -> Unit
) : ListAdapter<SpecificTopic, SubItemViewHolder>(DIFF_CALLBACK) {

    companion object {
        private val DIFF_CALLBACK = object : DiffUtil.ItemCallback<SpecificTopic>() {
            override fun areItemsTheSame(old: SpecificTopic, aNew: SpecificTopic) = (old.id == aNew.id)
            override fun areContentsTheSame(old: SpecificTopic, aNew: SpecificTopic) = (old == aNew)
        }
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): SubItemViewHolder {
        return SubItemViewHolder(parent.inflate(R.layout.sub_item))
    }

    override fun onBindViewHolder(holder: SpecificTopicViewHolder, position: Int) {
        holder.bind(getItem(position)!!, onClick)
    }

}
  

activity_chapter.xml

 <?xml version="1.0" encoding="utf-8"?>

<androidx.appcompat.widget.LinearLayoutCompat
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

        <androidx.recyclerview.widget.RecyclerView
            android:id="@ id/chapter_recycler_view"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
            tools:listitem="@layout/main_item"/>

</androidx.appcompat.widget.LinearLayoutCompat>
  

ChapterActivity.kt

 class ChapterActivity : BaseActivity<ChapterViewModel>() {

    var chapterPosition = 0

    private val mainItemAdapter: MainItemAdapter by lazy {
        MainItemAdapter { specificChapter, position ->
            // sub item Api call when clicked specific item. response is viewmodel.allTopics
            chapterPosition = position
            specificChapter.id?.let { viewModel.getChapterWiseTopics(it) }
        }
    }

    private val subItemAdapter: SubItemAdapter by lazy {
        SubItemAdapter {

        }
    }

    override fun onResume() {
        super.onResume()
        // Main item Api call. response is viewmodel.allChapters
        viewModel.getChapters("subject_code")
    }

    override fun observeLiveData() {
        // showing Main item in parent recyclerView
        observe(viewModel.allChapters) {
            val chapterList = ArrayList<SpecificChapter>()
            chapterList.add(SpecificChapter(...))

            chapter_recycler_view.adapter = mainItemAdapter
            mainItemAdapter.submitList(chapterList)
            chapter_recycler_view.setItemViewCacheSize(chapterList.size)
        }

        // showing sub item in nested recyclerView
        observe(viewModel.allTopics) {
            val topicList = ArrayList<SpecificTopic>()
            topicList.add(SpecificTopic(...))

            with((chapter_recycler_view.findViewHolderForAdapterPosition(chapterPosition) as MainItemViewHolder).itemView) {

                this.chapter_topic_recycler_view.adapter = subItemAdapter
                subItemAdapter.submitList(topicList)
            }
        }
    }
}