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