0

Redio button in recyclerview with kotlin, dagger2, retrofit , livedata, MVVM and databinding,I need updated list from videModel and also set selected positions to find it is selected and other on is deselected. please suggest how to select only one in RadioButton in List. here are my adapter:-

class DocTypeListAdapter : RecyclerView.Adapter<DocTypeListAdapter.ViewHolder>() {
    private lateinit var postList: List<DriverType>

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): DocTypeListAdapter.ViewHolder {
        val binding: ItemDocumentTypeBinding =
            DataBindingUtil.inflate(LayoutInflater.from(parent.context), R.layout.item_document_type, parent, false)
        return ViewHolder(binding)
    }

    override fun onBindViewHolder(holder: DocTypeListAdapter.ViewHolder, position: Int) {
        holder.bind(postList[position], position, mSelectedItem)
    }

    override fun getItemCount(): Int {
        return if (::postList.isInitialized) postList.size else 0
    }

    fun updatePostList(postList: List<DriverType>) {
        this.postList = postList
        notifyDataSetChanged()
    }

    class ViewHolder(private val binding: ItemDocumentTypeBinding) : RecyclerView.ViewHolder(binding.root) {
        private val viewModel = DocTypeListViewModel()

        fun bind(post: DriverType, position: Int, selectedPosition: Int) {
//            viewModel.bind(post,true)
            viewModel.bind(post,position,selectedPosition)

//             mRadioButton : RadioButton = binding.radioButton;



            viewModel.readioButtonClicked(getAdapterPosition(),position)
            binding.viewModel = viewModel
        }
    }
}

viewModel Like:-

class DocTypeListViewModel : BaseViewModel() {
    private val postTitle = MutableLiveData<String>()
    private val postBody = MutableLiveData<String>()
     val isChecked = MutableLiveData<Boolean>()
    private var mSelectedItem = -1


    fun bind(post: DriverType, position: Int, selectedPosition: Int) {
        postTitle.value = post.driver_type
        postBody.value = post.description

        if ((selectedPosition == -1 && position == 0))
            isChecked.value = true
        else
            if (selectedPosition == position)
                isChecked.value = true
            else
                isChecked.value = false

    }

    fun getPostTitle(): MutableLiveData<String> {
        return postTitle
    }

    fun getPostBody(): MutableLiveData<String> {
        return postBody
    }

    fun getIsChecked(): MutableLiveData<Boolean> {
        return isChecked
    }

    fun readioButtonClicked(selectedPosition: Int, pos:Int) {
        mSelectedItem = selectedPosition

        //            mSelectedItem=getAdapterPosition()
//            notifyDataSetChanged()

    }
}

my layout:-

<android.support.v7.widget.RecyclerView
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                app:adapter="@{viewModel.getDocTypeListAdapter()}"

                android:layout_marginTop="8dp"
                app:layout_constraintTop_toBottomOf="@+id/textView9"
                app:layout_constraintStart_toStartOf="parent"
                android:layout_marginStart="8dp"
                app:layout_constraintEnd_toEndOf="parent"
                android:layout_marginEnd="8dp"
                android:id="@+id/recyclerView"
                android:layout_marginBottom="8dp"
                app:layout_constraintBottom_toTopOf="@+id/button"/>

binding adpter:-

@BindingAdapter("adapter")
fun setAdapter(view: RecyclerView, adapter: RecyclerView.Adapter<*>) {
    view.adapter = adapter
}
Bink
  • 1,934
  • 1
  • 25
  • 41
Uday Nayak
  • 429
  • 4
  • 20

2 Answers2

1

I usually do like this :

class YourAdapter(val selected : (YourClassType) -> Unit) : RecyclerView.Adapter<RecyclerView.ViewHolder>() {

    // override fun onCreateViewHolder

    // override fun getItemCount()

    // override fun onBindViewHolder

    inner class YourViewHolder(val binding: YourClassItemBinding) : RecyclerView.ViewHolder(binding.root) {
        fun setData(item : YourItem) {
            binding.radioButton.setOnClickListener {
                binding.radioButton.checked = true
                selected.invoke(item) // use this if you need the item in your activity
            }
            // binding.viewModel.setData
        }
    }

}

But you will probably need to create your own function to uncheck other radioButtons items in the list when one is selected.

EDIT

I don't think it is a good practice to put the adapter in the xml file.

I usually do like this, in the activity that "owns" the RecyclerView :

class YourActivity : AppCompatActivity() {

    var listRv : RecyclerView? = null

    var viewModel = YourViewModel()

    var adapter = YourAdapter {
        // Put here the actions you want to achieve when a user click on an item and the adapter selected val is "invoked"
    }

    override fun onCreate(savedInstanceState : Bundle?) {
        super.onCreate()

        val binding = DataBindingUtil.setContentView<ActivityYourBinding>(this, R.layout.activity_your_layout)
        binding.viewModel = viewModel

        listRv = binding.yourListId
        listRv?.adapter = adapter // Set your list adapter here
        listRv?.layoutManager = LinearLayoutManager(this)


        // etc.
    }
}
Mathieu
  • 1,435
  • 3
  • 16
  • 35
0

If your using rxjava/rxkotlin then map operator will help you to achieve above

val item=YourModel()   
val observable:Observable<YourModel>
observable=Observable.fromIterable(list)
observable.map { model->
    model.isChecked = filter.modelType===item.modelType
    }
}.toList().subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe()

After map operation use updated list,it will produce result which you wanted.