繁体   English   中英

RecyclerView 和 LiveData

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM