kotlin - 如何为以下回收器视图编写适配器类?
问题描述
我正在尝试制作一个 Todo 应用程序,并且我已经完成了 Room 部分并且能够存储数据现在我想以 Recycler View 的形式显示数据,但我不知道如何编写与其对应的适配器类。我在不同的网站上寻找它,我从来没有得到任何令人满意的答案。
**TodoFragViewModel.kt""
class TodofragViewModel(
val database: TodoDao, applicaltion: Application
): AndroidViewModel(applicaltion) {
// TODO: Implement the ViewModel
/**
* viewModelJob allows us to cancel all coroutines started by this ViewModel.
*/
private var viewModelJob = Job()
/**All coroutines can be cancelled by viewmodelJob.cancel() and Dispatcher.main is byDefault choice
*/
private val uiScope = CoroutineScope(Dispatchers.Main + viewModelJob)
private val currenctTodo = MutableLiveData<Todo?>()
private val allTodo = database.getAllTodo()
init{
intializeThisTodo()
}
private fun intializeThisTodo(){
uiScope.launch {
currenctTodo.value=getFromDatabase()
}
}
private suspend fun getFromDatabase(): Todo? {
return withContext(Dispatchers.IO){
val info =database.getCurrentTodo()
info
}
}
private suspend fun insert(thisTodo: Todo) {
withContext(Dispatchers.IO) {
database.insert(thisTodo)
Log.i("Database","${database.getCurrentTodo()?.description} and ${database.getCurrentTodo()?.time}")
}
}
fun onAdded(time:String,description:String) {
uiScope.launch {
val thisTodo = Todo(time,description)
insert(thisTodo)
currenctTodo.value=getFromDatabase()
}
}
/**
* Called when the ViewModel is dismantled.
* At this point, we want to cancel all coroutines;
* otherwise we end up with processes that have nowhere to return to
* using memory and resources.
*/
override fun onCleared() {
super.onCleared()
viewModelJob.cancel()
}
}
todo_recycler_view
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent" android:layout_height="wrap_content">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="@+id/date_text"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_marginStart="16dp"
android:layout_marginTop="16dp"
android:layout_marginEnd="16dp"
android:text="TextView"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/todo_description"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginTop="16dp"
android:layout_marginEnd="16dp"
android:text="TextView"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/date_text" />
</androidx.constraintlayout.widget.ConstraintLayout>
TodoFrag.kt
class todofrag : Fragment() {
companion object {
fun newInstance() = todofrag()
}
private lateinit var viewModel: TodofragViewModel
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
return inflater.inflate(R.layout.todofrag_fragment, container, false)
}
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
val application = requireNotNull(this.activity).application
val dataSource= TodoDatabase.getInstance(application)?.InformationDatabaseDao
val viewModelFactory = dataSource?.let { TodoViewModelFactory(it, application) }
val viewModel=ViewModelProviders.of(this,viewModelFactory).get(TodofragViewModel::class.java)
add_button.setOnClickListener{
val currentDate: String = SimpleDateFormat("dd/MM/yyyy", Locale.getDefault()).format(Date())
val currentTime: String = SimpleDateFormat("HH:mm:ss", Locale.getDefault()).format(Date())
val time:String="${currentDate} \n ${currentTime}"
viewModel.onAdded(time,todo_text.text.toString())
}
}
}
请让我知道是否添加了任何其他文件。顺便说一句,我尝试使用卡片视图以使其看起来不错。
解决方案
开发人员文档很好地解释了它。
这可能不完全适合您的需要,但它应该是一个好的开始。具体来说,我不知道您的 Todo 类的所有字段,因此请确保您考虑了此代码中的那些字段。
基本上,你会想要一个ViewHolder
代表你的CardView
class TodoViewHolder(convertView: View) : RecyclerView.ViewHolder(convertView) {
val dateText = convertView.findViewById(R.id.date_text)
val description = convertView.findViewById(R.id.todo_description)
// whatever else you need access to
}
而且您会希望使用它DiffUtil
来获得更好的用户体验。当列表中的事物发生变化时,这允许一些动画,例如删除项目、编辑项目或添加项目。
private class TodoDiffCallback : DiffUtil.ItemCallback<Todo>() {
override fun areItemsTheSame(oldItem: Todo, newItem: Todo) =
oldItem.id == newItem.id
override fun areContentsTheSame(oldItem: Todo, newItem: Todo) =
oldItem.dateText == newItem.dateText && oldItem.description == newItem.description
}
你会想要扩展ListAdapter
和覆盖它的方法。为您看到的每个视图onCreateViewHolder
创建一个实例,并允许您向列表中的每个项目添加行为。值得注意的是,如果需要,您可以将参数传递给适配器。TodoViewHolder
onBindViewHolder
class MyListAdapter : ListAdapter<Todo, TodoViewHolder>(TodoDiffCallback()) {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) = TodoViewHolder(LayoutInflater.from(parent.context).inflate(R.layout.todo_recycler_view, parent, false))
override fun onBindViewHolder(holder: TodoViewHolder, position: Int) {
val todo = getItem(position)
holder.dateText = todo.dateText
holder.description = todo.description
// add whatever click listener and other stuff you need
}
}
在您的片段中,当您访问您的 时RecyclerView
,只需添加一个适配器实例(如果它为空)。
if (recyclerView.adapter == null) {
recyclerView.adapter = TotoListAdapter()
}
当您想要将数据(您从 Room 或您的 API 检索到的数据)添加到适配器(在片段/活动中)时,只需执行以下操作:
(recyclerView.adapter as? TodoListAdapter)?.submitList(data)
在旁注中,确保清理您的样式(您可以使用菜单Reformat Code
中的命令Code
),并且您希望将其重命名todo_recycler_view
为todo_view
. 您将希望RecyclerView
在片段布局中有一个布局。
推荐阅读
- kubernetes - ebs.csi.aws.com 与 kubernetes.io/aws-ebs 的供应商有何区别?
- java - java 8中的雪花时间戳转换
- google-apps-script - 如何通过引用 URL 编写函数来计算其他电子表格中的工作表数量
- sql - 根据两列重复值找出唯一的顶部记录
- regex - 正则表达式从 X 到 Y 但不包括另一个 X
- arrays - 如何在数据库中保存 JSON - laravel 8
- c# - 通过 C# Web 窗体对 Windows 用户进行身份验证
- python - 使用 python-telegram-bot 包向电报机器人发送语音命令
- c - Visual Studio 2019 的“无符号 __int128”
- flutter - 在使用 Google 登录时获取新的 Google 令牌