首页 > 解决方案 > 如何为以下回收器视图编写适配器类?

问题描述

我正在尝试制作一个 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())

        }

    }

}

请让我知道是否添加了任何其他文件。顺便说一句,我尝试使用卡片视图以使其看起来不错。

标签: kotlinandroid-roomandroid-recyclerview

解决方案


开发人员文档很好地解释了它。

这可能不完全适合您的需要,但它应该是一个好的开始。具体来说,我不知道您的 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创建一个实例,并允许您向列表中的每个项目添加行为。值得注意的是,如果需要,您可以将参数传递给适配器。TodoViewHolderonBindViewHolder

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_viewtodo_view. 您将希望RecyclerView在片段布局中有一个布局。


推荐阅读