Recycler View 不使用 livedata 更新

问题描述

我正在尝试使用 Recycler 视图 + 实时数据 + 房间数据库 库制作 Todo 应用程序。我知道不使用 viewmodel 这很荒谬,但是我让我的导师这样做,这个项目要在 viewmodel 讲座之前提交,他已经展示了他如何已经完成,但我陷入困境的问题是,当数据库内容发生更改时,我的回收站视图没有更新,我不明白为什么?请有人检查我的项目并调试它。

  1. MainActivity.kt

<pre>
package com.soham.todo

import android.content.Intent
import android.os.Bundle
import android.view.Menu
import android.view.MenuItem
import androidx.appcompat.app.AppCompatActivity
import androidx.lifecycle.Observer
import androidx.recyclerview.widget.linearlayoutmanager
import androidx.room.Room
import com.soham.rcv_prac.myAdapter
import kotlinx.android.synthetic.main.activity_main.*
import kotlinx.coroutines.*

class MainActivity : AppCompatActivity() {

    private val db by lazy {
        Room.databaseBuilder(
            this,AppDataBase::class.java,"todo.db"
        ).allowMainThreadQueries()
            .fallbackToDestructiveMigration()
            .build()
    }

    val ls = arraylistof<Todo>()
    private val ad = myAdapter(ls)

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        setContentView(R.layout.activity_main)
        setSupportActionBar(findViewById(R.id.materialToolbar))

        floatingActionButton.setonClickListener {
            val i = Intent(this,editTodo::class.java)
            startActivity(i)
        }



        db.DAO1().getTask().observe(this,Observer {
            if (!it.isNullOrEmpty()) {
                ls.clear()
                ls.addAll(it)
                ad.notifyDataSetChanged()
            } else {
                ls.clear()
                ad.notifyDataSetChanged()
            }
        })

        recyclerView.apply {
            layoutManager = linearlayoutmanager(this@MainActivity)
            adapter = ad
        }
    }

    override fun onCreateOptionsMenu(menu: Menu?): Boolean {

        menuInflater.inflate(R.menu.menu_layout,menu)
        return super.onCreateOptionsMenu(menu)
    }

    override fun onoptionsItemSelected(item: MenuItem): Boolean {

        when (item.itemId) {
            R.id.historyOption -> {
                startActivity(Intent(this,HistoryActivity::class.java))
            }
        }

        return super.onoptionsItemSelected(item)
    }
}
</pre>

  1. Todo.kt myAdapter.kt

<pre>
package com.soham.todo

import androidx.room.Entity
import androidx.room.PrimaryKey
import androidx.room.TypeConverters
import java.util.*

@Entity(tableName = "todoTable")
data class Todo(
    val title: String,val description: String,val category: String,@TypeConverters
    val date: Calendar,//    val time: Long,val isFinished: Int = -1,@PrimaryKey(autoGenerate = true)
    val id: Long = 0
)
</pre>

  1. AppDataBase.kt

我已经评论了这个文件的某些部分,因为我认为它会导致问题。

<pre>
package com.soham.todo

import android.content.Context
import androidx.room.Database
import androidx.room.Room
import androidx.room.RoomDatabase
import androidx.room.TypeConverters

@Database(entities = [Todo::class],version = 1,exportSchema = false)
@TypeConverters(dateConverter::class)
abstract class AppDataBase : RoomDatabase() {
    abstract fun DAO1(): DAO

//
//    companion object {
//        // Singleton prevents multiple instances of database opening at the
//        // same time.
//        @Volatile
//        private var INSTANCE: AppDataBase? = null
//
//        fun getDatabase(context: Context): AppDataBase {
//            // if the INSTANCE is not null,then return it,//            // if it is,then create the database
//            return INSTANCE ?: synchronized(this) {
//                val instance = Room.databaseBuilder(
//                    context.applicationContext,//                    AppDataBase::class.java,//                    "todo.db"
//                ).build()
//                INSTANCE = instance
//                // return instance
//                instance
//            }
//        }
//    }

}
</pre>

  1. DAO.kt

<pre>
package com.soham.todo

import androidx.lifecycle.LiveData
import androidx.room.Dao
import androidx.room.Insert
import androidx.room.OnConflictStrategy
import androidx.room.Query

@Dao
interface DAO {

    @Insert(onConflict = OnConflictStrategy.IGnorE)
    fun insertTodo(todo: Todo): Long

    @Query("SELECT * from todoTable where isFinished != -1")
    fun getTask(): LiveData<List<Todo>>

    @Query("Update todoTable set isFinished = 1 where id=:uid")
    fun finishTask(uid: Long)

    @Query("Delete from todoTable where id=:uid")
    fun deleteTask(uid: Long)

}
</pre>

  1. editTodo.kt

<pre>
package com.soham.todo

import android.app.DatePickerDialog
import android.app.TimePickerDialog
import android.os.Bundle
import android.view.View
import android.widget.ArrayAdapter
import android.widget.DatePicker
import android.widget.TimePicker
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import androidx.room.Room
import kotlinx.android.synthetic.main.activity_edit_todo.*
import java.text.SimpleDateFormat
import java.util.*


const val DB_NAME = "todo.db"

class editTodo : AppCompatActivity(),View.OnClickListener {

    private val db by lazy {
        Room.databaseBuilder(
            this,DB_NAME
        ).allowMainThreadQueries()
            .fallbackToDestructiveMigration()
            .build()
    }

    lateinit var tmpCalender: Calendar

    private val categoryList = arraylistof<String>("Office","Insurance","Business","Travel","Family","Shopping")

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_edit_todo)

        val selectedDate = dateSelector.setonClickListener(this)
        timeSelector.setonClickListener(this)
        setupSpinner()

        saveButton.setonClickListener {
            Toast.makeText(this,tmpCalender.time.toString(),Toast.LENGTH_LONG).show()

            db.DAO1().insertTodo(
                Todo(
                    titleBox.text.toString(),explainBox.text.toString(),spinner.selectedItem.toString(),tmpCalender,1,titleBox.text.hashCode().toLong()
                )
            )

        }
    }

    private fun setupSpinner() {
        val aa: ArrayAdapter<String> = ArrayAdapter<String>(
            this,android.R.layout.simple_list_item_1,categoryList
        )
//        aa.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
        spinner.adapter = aa
    }

    override fun onClick(v: View) {
        when (v.id) {
            dateSelector.id -> makeDateSelector()
            timeSelector.id -> makeTimeSelector()
            spinner.id -> setupSpinner()
        }
    }

    private fun makeDateSelector() {
        tmpCalender = Calendar.getInstance()
        val dateSetListener = DatePickerDialog.OnDateSetListener { datePicker: DatePicker,year: Int,month: Int,dayOfMonth: Int ->
            tmpCalender.set(Calendar.YEAR,year)
            tmpCalender.set(Calendar.MONTH,month)
            tmpCalender.set(Calendar.DAY_OF_MONTH,dayOfMonth)
            updateDate(tmpCalender)
        }

        val datePickerDialog = DatePickerDialog(
            this,dateSetListener,tmpCalender.get(Calendar.YEAR),tmpCalender.get(Calendar.MONTH),tmpCalender.get(Calendar.DAY_OF_MONTH)
        )
        datePickerDialog.datePicker.minDate = System.currentTimeMillis()
        datePickerDialog.show()
    }

    private fun makeTimeSelector() {
        tmpCalender = Calendar.getInstance()
        val dateSetListener = TimePickerDialog.OnTimeSetListener { timePicker: TimePicker,hourOfDay: Int,minute: Int ->
            tmpCalender.set(Calendar.HOUR_OF_DAY,hourOfDay)
            tmpCalender.set(Calendar.MINUTE,minute)
            updateDate(tmpCalender)
        }

        val timePickerDialog = TimePickerDialog(
            this,tmpCalender.get(Calendar.HOUR_OF_DAY),tmpCalender.get(Calendar.MINUTE),false
        )
        timePickerDialog.show()
        updateTime(tmpCalender)
    }

    private fun updateTime(tmpCalender: Calendar) {
        val format = "h:mm a"
        val sdf = SimpleDateFormat(format)
        timeBox.setText(sdf.format(tmpCalender.time))
    }

    private fun updateDate(tmpCalender: Calendar) {
        //Mon,5 Jan 2020
        val format = "EEE,d MM yyyy"
        val sdf = SimpleDateFormat(format)
        dateBox.setText(sdf.format(tmpCalender.time))

        timeBox.visibility = View.VISIBLE
        timeSelector.visibility = View.VISIBLE
    }
}
</pre>

  1. dateConverter.kt

<pre>
package com.soham.todo

import android.util.Log
import androidx.room.TypeConverter
import java.util.*

class dateConverter {
    @TypeConverter
    fun StringtoDate(value: String): Calendar {
        val cal: Calendar = Calendar.getInstance()
        val month = when (value.slice(4..6)) {
            "Jan" -> 1
            "Feb" -> 2
            "Mar" -> 3
            "Apr" -> 4
            "May" -> 5
            "Jun" -> 6
            "Jul" -> 7
            "Aug" -> 8
            "Sep" -> 19
            "Oct" -> 10
            "Nov" -> 11
            "Dec" -> 12
            else -> -1
        }
        val lastIndex = value.length - 1
        val year = value.slice(lastIndex - 3..lastIndex)

        val hour = value.slice(11..12)
        val min = value.slice(14..15)

        value.slice(8..9).let { cal.set(Calendar.DAY_OF_MONTH,it.toInt()) }
        Log.e(null,month.toInt().toString())
        cahttps://stackoverflow.com/posts/67793056/edit#l.set(Calendar.MONTH,month.toInt())
        Log.e(null,year.toInt().toString())
        cal.set(Calendar.YEAR,year.toInt())
        cal.set(Calendar.HOUR_OF_DAY,hour.toInt())
        cal.set(Calendar.MINUTE,min.toInt())


        return cal
    }

    @TypeConverter
    fun CalenderToString(cal: Calendar): String {
        return cal.time.toString()
    }
}

</pre>

它在打开时显示数据库内容,但是当我添加待办事项时,它不会自行更新。要更新它,我必须关闭并重新打开应用程序或旋转设备以重新创建活动。

这是 git 链接https://github.com/soham04/ToDo_app.git (检查 tmpBranch 不是 master 分支)

我在使用代码选项添加代码时遇到问题,这就是我使用此选项的原因

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...