如何从 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 时。
- 如何从 MutableLiveData
> 填充 RecycleView。
- 如何从 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()
}
}
首先,我会给你一个我的代码示例,并在下面描述问题。
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 时。
- 如何从 MutableLiveData
> 填充 RecycleView。 - 如何从 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()
}
}