Reputation: 1025
First I'll give you an example of my code and describe the problem below.
MainViewModel
class MainViewModel @ViewModelInject constructor(private val ordersRepository: OrdersRepository) :
ViewModel() {
private val _orderList = MutableLiveData<State<List<Order>>>()
val orderList: LiveData<State<List<Order>>>
get() = _orderList
fun getOrders() {
viewModelScope.launch {
ordersRepository.getAllOrders().collect {
Log.d("test2",it.toString())
_orderList.value = it
}
}
}
}
HomeItemAdapter
class HomeItemAdapter(private val viewModel: MainViewModel) : ListAdapter < Order,
HomeItemAdapter.ViewHolder > (HomeItemDiffCallback()) {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) : ViewHolder {
val inflater = LayoutInflater.from(parent.context)
return ViewHolder(inflater.inflate(R.layout.item_main, parent, false))
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
holder.bind(position)
}
inner class ViewHolder(val view: View) : RecyclerView.ViewHolder(view) {
private val title: TextView = view.findViewById(R.id.item_title)
fun bind(pos: Int) {
var value = viewModel.orderList.value
Log.d("test", value.toString())
title.text = viewModel.orderList.value.data toString()
view.setOnClickListener {
view.findNavController().navigate(R.id.action_homeFragment_to_orderFragment, setupInputData2(adapterPosition).arguments)
}
}
}
private fun setupInputData2(adapterPosition: Int) : NavDirections {
return HomeFragmentDirections.actionHomeFragmentToOrderFragment(adapterPosition)
}
class HomeItemDiffCallback: DiffUtil.ItemCallback < Order > () {
override fun areItemsTheSame(oldItem: Order, newItem: Order) : Boolean = oldItem == newItem
override fun areContentsTheSame(oldItem: Order, newItem: Order) : Boolean = oldItem == newItem
}
}
HomeFragment
@ExperimentalCoroutinesApi
@AndroidEntryPoint
class HomeFragment : BaseFragment<MainViewModel, FrgMainBinding>() {
override val mViewModel: MainViewModel by viewModels()
private lateinit var recycler: RecyclerView
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?): View {
return inflater.inflate(R.layout.frg_main, container, false)
}
private fun getOrders() {
mViewModel.getOrders()
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
activity?.let {
setRecyclerItemsObserver()
}
}
private fun initOrders() {
mViewModel.orderList.observe(this) { state ->
when (state) {
is State.Loading -> showLoading(true)
is State.Success -> {
if (state.data.isNotEmpty()) {
(recycler.adapter as? HomeItemAdapter)?.submitList(state.data.toMutableList())
showLoading(false)
}
}
is State.Error -> {
showToast(state.message)
showLoading(false)
}
}
}
//TODO
/*swipeRefreshLayout.setOnRefreshListener {
getOrders()
}*/
// If State isn't `Success` then reload posts.
if (mViewModel.orderList.value !is State.Success) {
getOrders()
}
}
private fun showLoading(isLoading: Boolean) {
// swipeRefreshLayout.isRefreshing = isLoading
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
// set fab listener to start an action
view.addNewButton.setOnClickListener(Navigation.createNavigateOnClickListener(R.id.action_create, null))
recycler = view.recycler
setupRecycler()
}
private fun setRecyclerItemsObserver() {
initOrders()
}
private fun setupRecycler() {
recycler.layoutManager = LinearLayoutManager(context)
val itemDecor = DividerItemDecoration(context, RecyclerView.VERTICAL)
recycler.addItemDecoration(itemDecor)
recycler.adapter = HomeItemAdapter(mViewModel)
}
override fun getViewBinding(): FrgMainBinding {
return FrgMainBinding.inflate(layoutInflater)
}
}
My question
My problem occurs when creating a Holder by Recycle View.
I will be glad to see an example of the code on kotlin to solve my problem Thanks!
Updated:
My problem is that I can't bind the object. Because I used to get it from the list and could do
private var title: TextView = view. findViewById(R. id.item_title)
title = list Product[position]. title
and now I can't get its object!
Upvotes: 1
Views: 1272
Reputation:
Use this fragment
inner class YouViewHolder(val view: View) : RecyclerView.ViewHolder(view) {
private val title: TextView = view.findViewById(R.id.product_name)
private val count: TextView = view.findViewById(R.id.product_count)
private val price: TextView = view.findViewById(R.id.product_price)
fun bind(pos: Int) {
title.text = mOrders?.get(pos)?.name
price.text = mOrders?.get(pos)?.price
count.text = pos.toString()
}
}
Upvotes: 0
Reputation: 866
Add a parameter to your adapter's constructor of the type List which is the initial list that you want to populate your RecyclerView with. submitList is a method that is called when in the course of lifecycle of the adpater, you want to send updated list to the adapter. (Say when your list changes)
class HomeItemAdapter() : ListAdapter<Order,
HomeItemAdapter.ViewHolder> (HomeItemDiffCallback()) {
private var mOrders: MutableList<Order?>? = null
private val mViewModel : MainViewModel
constructor(private val viewModel: MainViewModel, listOrders : MutableList<Order?>?) : this() {
mOrders = listOrders
mViewModel = viewModel
}
fun submitList(newOrders: List<Order>) {
val diffCallBack = HomeItemDiffCallback(this.mOrders, new Orders)
val diffResult = DiffUtil.calculateDiff(diffCallback)
this.mOrders.clear()
this.mOrders.addAll(newOrders)
diffResult.dispatchUpdatesTo(this)
}
Your callback
class HomeItemDiffCallback(
private val oldList: List<Order>,
private val newList: List<Order>
) : DiffUtil.ItemCallback() {
override fun areItemsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean {
return oldList[oldItemPosition].id == newList[newItemPosition].id
}
override fun areContentsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean {
return oldList.get(oldItemPosition).equals(newList.get(newItemPosition));
}
}
In my view in your HomeFragment, you should first call setupRecycler()
and then setRecyclerItemsObserver()
While setting up a recycler if you don't have a list you want to pass, you can simple send null here,
recycler.adapter = HomeItemAdapter(mViewModel, null)
When you receive the list in initOrders()
, do what you are currently doing i.e
(recycler.adapter as? HomeItemAdapter)?.submitList(state.data.toMutableList())
Upvotes: 1