Le *_*Anh 5 android kotlin android-recyclerview android-livedata android-listadapter
我已经使用普通的ViewAdapter成功完成了此操作,但我似乎无法使用ListAdapter来完成此操作。
这是我的片段,它完成了大部分工作:
class CrimeListFragment: Fragment() {
//Required interface for hosting activities
interface Callbacks {
fun onCrimeSelected(crimeId: UUID)
}
private var callbacks: Callbacks? = null
private lateinit var crimeRecyclerView: RecyclerView
private val crimeListViewModel: CrimeListViewModel by lazy {
ViewModelProviders.of(this).get(CrimeListViewModel::class.java)
}
override fun onAttach(context: Context) {
super.onAttach(context)
callbacks = context as Callbacks?
}
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
val view = inflater.inflate(R.layout.fragment_crime_list, container, false)
crimeRecyclerView =
view.findViewById(R.id.crime_recycler_view) as RecyclerView
crimeRecyclerView.layoutManager = LinearLayoutManager(context)
crimeRecyclerView.adapter = CrimeListAdapter(emptyList())
return view
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
crimeListViewModel.crimeListLiveData.observe(
viewLifecycleOwner,
Observer { crimes ->
crimes?.let {
Log.i(TAG, "Got crimes ${crimes.size}")
updateUI(crimes)
}
}
)
}
override fun onDetach() {
super.onDetach()
callbacks = null
}
private fun updateUI(crimes: List<Crime>) {
crimeRecyclerView.adapter = CrimeListAdapter(crimes)
}
companion object {
fun newInstance(): CrimeListFragment {
return CrimeListFragment()
}
}
private inner class CrimeHolder(view: View)
: RecyclerView.ViewHolder(view), View.OnClickListener {
private lateinit var crime: Crime
private val titleTextView = itemView.findViewById<TextView>(R.id.crime_title)
private val dateTextView = itemView.findViewById<TextView>(R.id.crime_date)
private val solvedImageView = itemView.findViewById<ImageView>(R.id.crime_solved)
init {
itemView.setOnClickListener(this)
}
fun bind(crime: Crime) {
this.crime = crime
titleTextView.text = crime.title
dateTextView.text = crime.date.toString()
solvedImageView.visibility = if(crime.isSolved) {
View.VISIBLE
} else {
View.GONE
}
}
override fun onClick(v: View) {
callbacks?.onCrimeSelected(crime.id)
}
}
private inner class CrimeListAdapter(var crimes: List<Crime>)
: ListAdapter<Crime, CrimeHolder>(DiffCallback()) {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): CrimeHolder {
val view =
layoutInflater.inflate(R.layout.list_item_crime, parent, false)
return CrimeHolder(view)
}
override fun onBindViewHolder(holder: CrimeHolder, position: Int) {
holder.bind(crimes[position])
}
}
private inner class DiffCallback: DiffUtil.ItemCallback<Crime>() {
override fun areItemsTheSame(oldItem: Crime, newItem: Crime): Boolean {
return oldItem.id == newItem.id
}
override fun areContentsTheSame(oldItem: Crime, newItem: Crime): Boolean {
return oldItem == newItem
}
}
}
Run Code Online (Sandbox Code Playgroud)
这是片段的视图模型:
class CrimeListViewModel: ViewModel() {
private val crimeRepository = CrimeRepository.get()
val crimeListLiveData = crimeRepository.getCrimes() //returns LiveData<List<Crime>>
}
Run Code Online (Sandbox Code Playgroud)
Android 文档中有关于ListAdapter 的内容:
虽然使用LiveData是向适配器提供数据的一种简单方法,但这不是必需的 -当新列表可用时,您可以使用SubmitList(List) 。
我应该在每次更新 UI 时提交一个新列表,而不是创建一个新的ListAdapter对象。但crimeRecyclerView.adapter没有任何.submitList()功能。那么我如何传递新列表呢?
LiveData对我来说还是个新东西,所以我对此不太清楚。我已经观察到存储在我的视图模型中的LiveData。那么这次我观察到什么呢?或者我只是将代码添加到现有的Observer中?
最后,当我在这种状态下运行代码时,手机显示一个空的RecyclerView。只UpdateUI()被调用, 的任何CrimeListAdapter函数都不会被调用。我不确定这是否是一个真正的问题,或者只是上述问题的结果。
1.我应该在每次更新 UI 时提交一个新列表,而不是创建一个新的 ListAdapter 对象。但是crimeRecyclerView.adapter没有.submitList()函数。那么我如何传递新列表呢?
crimeRecyclerView.adapter返回RecyclerView.Adapter类型
submitList()是ListAdapter的方法,RecyclerView.Adapter的子类
在调用该方法之前,您需要从父类转换为子类,如下所示。
(crimeRecyclerView.adapter as CrimeListAdapter).submitList(crimes)
Run Code Online (Sandbox Code Playgroud)
2.LiveData对我来说还是个新东西,所以我对此不太清楚。我已经观察到存储在我的视图模型中的 LiveData。那么这次我观察到什么呢?或者我只是将代码添加到现有的观察者中?
您这部分的代码很好,无需执行更多操作。
3.最后当我在这种状态下运行代码时,手机显示一个空的RecyclerView。仅调用 UpdateUI(),不调用 CrimeListAdapter 的任何函数。我不确定这是否是一个真正的问题,或者只是上述问题的结果。
使用 ListAdapter 的最好部分是您不需要向构造函数提供数据列表(在您的情况下是犯罪)。
回到你的代码,你需要改变 3 件事。
// crimeRecyclerView.adapter = CrimeListAdapter(emptyList())
crimeRecyclerView.adapter = CrimeListAdapter()
Run Code Online (Sandbox Code Playgroud)
和
// crimeRecyclerView.adapter = CrimeListAdapter(crimes)
(crimeRecyclerView.adapter as CrimeListAdapter).submitList(crimes)
Run Code Online (Sandbox Code Playgroud)
和
//private inner class CrimeListAdapter(var crimes: List<Crime>) :
// ListAdapter<Crime, CrimeHolder>(DiffCallback()) {
//
// override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): CrimeHolder {
// val view = layoutInflater.inflate(R.layout.list_item_crime, parent, false)
// return CrimeHolder(view)
// }
//
// override fun onBindViewHolder(holder: CrimeHolder, position: Int) {
// holder.bind(crimes[position])
// }
//}
private inner class CrimeListAdapter : ListAdapter<Crime, CrimeHolder>(DiffCallback()) {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): CrimeHolder {
val view = layoutInflater.inflate(R.layout.list_item_crime, parent, false)
return CrimeHolder(view)
}
override fun onBindViewHolder(holder: CrimeHolder, position: Int) {
holder.bind(getItem(position))
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
3439 次 |
| 最近记录: |