[英]RecyclerView and LiveData
我正在学习在 RecyclerView 中使用 LiveData。 我有一个包含 2 个片段的应用程序。 一个用于 RecyclerView,另一个用于向其中添加新项目。 在第一个中,我执行以下操作:
mAdapter = EquipAdapter()
recyclerView.apply {
layoutManager = LinearLayoutManager(activity)
setHasFixedSize(true)
adapter = mAdapter
}
mViewModel = (activity as MainActivity).viewmodel
mViewModel.getAllMoves().observe(viewLifecycleOwner, Observer{
Log.d("TAG", "Get Live Data")
mAdapter.setList(it)
})
在适配器中:
fun setList(itemList: List<EquipMove>) {
this.itemList = itemList
notifyDataSetChanged()
Log.d("TAG", "Setting itemList")
}
当我启动应用程序时,我会得到带有以下行的 LogCat:
2020-09-06 11:31:42.459 25304-25304/ru.albeiz.equipmover D/TAG: Get Live Data
2020-09-06 11:31:42.460 25304-25304/ru.albeiz.equipmover D/TAG: Setting itemList
然后我开始第二个片段,作为它工作的结果,我在 Room 中添加了一个新项目。 之后片段关闭,我回到第一个片段。 现在我有这样的 LogCat:
2020-09-06 11:32:19.669 25304-25304/ru.albeiz.equipmover D/TAG: Get Live Data
2020-09-06 11:32:19.669 25304-25304/ru.albeiz.equipmover D/TAG: Setting itemList
2020-09-06 11:32:19.838 25304-25304/ru.albeiz.equipmover D/TAG: Get Live Data
2020-09-06 11:32:19.839 25304-25304/ru.albeiz.equipmover D/TAG: Setting itemList
即看起来 LiveData 被观察了两次,出于某种原因,回收器适配器两次获取列表:使用旧项目,然后使用新项目。 最后,我有混合项目的回收站视图。 如果我开始第二个片段并返回而不添加任何内容,则回收器会正确显示数据。 如果我重新启动应用程序,回收站也会显示它必须的所有内容。
你能解释一下我做错了什么吗?
class FirstFragment : Fragment() {
private val TAG = "FirstFragment"
private lateinit var mViewModel: EquipViewModel
private lateinit var mAdapter: EquipAdapter
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_equip_list, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
fab.setOnClickListener {
mNewMoveCaller.createNewMove()
}
initRecyclerView()
mViewModel = ViewModelProvider(requireActivity()).get(EquipViewModel::class.java)
mViewModel.getAllMoves().observe(viewLifecycleOwner, Observer{
Log.d("TAG", "Get Live Data")
mAdapter.setList(it)
})
}
private fun initRecyclerView() {
mAdapter = EquipAdapter()
recyclerView.apply {
layoutManager = LinearLayoutManager(activity)
setHasFixedSize(true)
adapter = mAdapter
}
}
}
class SecondFragment : Fragment() {
private lateinit var mViewModel: EquipViewModel
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setHasOptionsMenu(true)
}
override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
inflater.inflate(R.menu.menu_new_move, menu)
super.onCreateOptionsMenu(menu, inflater)
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {
when (item.itemId) {
R.id.miSaveMove -> {
saveNewMove()
}
}
return true
}
private fun saveNewMove() {
val newEquipMove = EquipMove(
null,
etNewCode.text.toString(),
Date().time,
//"spDestination.selectedItem.toString()"
"someText"
)
mViewModel.insert(newEquipMove)
exitFragment()
}
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_new_move, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
val activity = requireActivity() as AppCompatActivity
activity.setSupportActionBar(frag_new_move_toolbar)
activity.supportActionBar?.setDisplayHomeAsUpEnabled(true)
activity.supportActionBar?.title = "Add a new move"
frag_new_move_toolbar.setNavigationOnClickListener {
exitFragment()
}
mViewModel = ViewModelProvider(requireActivity()).get(EquipViewModel::class.java)
btnSaveNewMove.setOnClickListener {
saveNewMove()
}
}
private fun exitFragment() {
requireActivity().onBackPressed()
}
}
class EquipAdapter(private var itemList: List<EquipMove> = listOf()):
RecyclerView.Adapter<EquipAdapter.EquipViewHolder>() {
inner class EquipViewHolder(itemView: View): RecyclerView.ViewHolder(itemView)
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): EquipViewHolder {
val view = LayoutInflater.from(parent.context)
.inflate(R.layout.recview_item, parent, false)
return EquipViewHolder(view)
}
override fun getItemCount(): Int {
return itemList.size
}
override fun onBindViewHolder(holder: EquipViewHolder, position: Int) {
holder.itemView.apply {
tvEquipmentCode.append(itemList[position].equipCode)
tvDestination.append(itemList[position].moveDestination)
tvMoveDate.append(itemList[position].moveDate.toString())
}
}
fun setList(itemList: List<EquipMove>) {
this.itemList = itemList
notifyDataSetChanged()
Log.d("TAG", "Setting itemList")
}
}
class EquipViewModel(application: Application): AndroidViewModel(application) {
private val equipRepository = EquipRepository(application)
private val allMoves = equipRepository.getAllMoves()
fun insert(equipMove: EquipMove) {
viewModelScope.launch {
equipRepository.insert(equipMove)
}
}
fun deleteAll() {
viewModelScope.launch {
equipRepository.deleteAll()
}
}
fun delete(equipMove: EquipMove) {
viewModelScope.launch {
equipRepository.delete(equipMove)
}
}
fun getAllMoves() : LiveData<List<EquipMove>> {
return allMoves
}
}
您需要在每个片段中初始化视图模型,例如
删除这一行
mViewModel = (activity as MainActivity).viewmodel
并添加此行
mViewModel = ViewModelProviders(activity)[MainViewModel::class.java]
然后使用观察方法。 不会有两面派
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.