如何从 MutableLiveData 获取元素

How to get element from MutableLiveData

首先,我会给你一个我的代码示例,并在下面描述问题。

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

我的问题

我的问题发生在通过回收视图创建 Holder 时。

  1. 如何从 MutableLiveData> 填充 RecycleView。
  2. 如何从 MutableLiveData 获取元素以获取其字段。

我很高兴看到 kotlin 上的代码示例来解决我的问题 谢谢!

更新:

我的问题是无法绑定对象。 因为我曾经从列表中获取它并且可以做到


private var title: TextView = view. findViewById(R. id.item_title)
title = list Product[position]. title 

现在我无法获取它的对象!

更新 v2 有错误

将一个参数添加到适配器的类型为 List 的构造函数,这是您要用来填充 RecyclerView 的初始列表。 submitList 是在适配器的生命周期过程中调用的方法,您想要将更新的列表发送到适配器。 (说明您的列表何时更改)

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

您的回电

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

}

在我看来,在你的 HomeFragment 中,你应该先调用 setupRecycler(),然后再调用 setRecyclerItemsObserver()

在设置回收站时,如果您没有要传递的列表,您可以在这里简单地发送 null,

recycler.adapter = HomeItemAdapter(mViewModel, null)

当您收到 initOrders() 中的列表时,请执行您当前正在执行的操作,即

(recycler.adapter as? HomeItemAdapter)?.submitList(state.data.toMutableList())

使用这个片段

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

    }
}