Kotlin SQlite:选择记录时应用程序崩溃

Kotlin SQlite: Application crashes when selecting a record

我正在尝试使用 kotlin 语言在 Android studio 中将 int 值实现到我的简单 sqlite 程序中。

我是 Kotlin 的初学者,所以我首先只使用字符串制作了一个 sqlite 程序,但现在我想使用 Int 值。

我设法使值成为 int 并插入工作正常,但是在选择记录时,应用程序崩溃。

这是日志猫。

15115-15115/com.example.sqlitedemo E/AndroidRuntime: FATAL EXCEPTION: main Process: com.example.sqlitedemo, PID: 15115 android.content.res.Resources$NotFoundException: String resource ID #0x3 at android.content.res.Resources.getText(Resources.java:444) at android.widget.TextView.setText(TextView.java:6412) at com.example.sqlitedemo.MainActivity$onCreate.invoke(MainActivity.kt:49)

错误 kt 49 和 44:与

有关
    adapter?.setOnClickItem {
        Toast.makeText(this,it.name,Toast.LENGTH_SHORT).show()
        //レコード更新
        edName.setText(it.name)
        edEmail.setText(it.email)
        edBuyAmount.setText(it.buyamount)
        edUseAmount.setText(it.useamount)
        std = it
    }

    at com.example.sqlitedemo.MainActivity$onCreate.invoke(MainActivity.kt:44)
    at com.example.sqlitedemo.StudentAdapter.onBindViewHolder$lambda-0(StudentAdapter.kt:32)

错误 kt:32 与

有关
override fun onBindViewHolder(holder: StudentViewHolder, position: Int) {
    val std = stdList[position]
    holder.bindView(std)
    holder.itemView.setOnClickListener{onClickItem?.invoke(std)}
    holder.btnDelete.setOnClickListener{onClickDeleteItem?.invoke(std)}
}

    at com.example.sqlitedemo.StudentAdapter.$r8$lambda$rFSStv71TK0PX1i3mffPAEhmz7s(Unknown Source:0)
    at com.example.sqlitedemo.StudentAdapter$$ExternalSyntheticLambda1.onClick(Unknown Source:4)
    at android.view.View.performClick(View.java:7448)
    at android.view.View.performClickInternal(View.java:7425)
    at android.view.View.access00(View.java:810)
    at android.view.View$PerformClick.run(View.java:28305)
    at android.os.Handler.handleCallback(Handler.java:938)
    at android.os.Handler.dispatchMessage(Handler.java:99)
    at android.os.Looper.loop(Looper.java:223)
    at android.app.ActivityThread.main(ActivityThread.java:7656)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947)

MainActivity class()

class MainActivity : AppCompatActivity() {

private lateinit var edName: EditText
private lateinit var edEmail: EditText
private lateinit var edBuyAmount:EditText
private lateinit var edUseAmount:EditText
private lateinit var btnAdd: Button
private lateinit var btnView: Button
private lateinit var btnUpdate: Button

private lateinit var sqLiteHelper: SQLiteHelper
private lateinit var recyclerView: RecyclerView
private  var adapter: StudentAdapter?=null
private var std:StudentModel?=null

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

    initView()
    initRecyclerView()
    sqLiteHelper= SQLiteHelper(this)
    //Show recycler view
    val stdList = sqLiteHelper.getAllStudent()
    Log.e("ok","${stdList.size}")

    adapter?.addItems(stdList)

    btnAdd.setOnClickListener{ addStudent()}
    btnView.setOnClickListener{getStudents()}
    btnUpdate.setOnClickListener{updateStudent()}
    adapter?.setOnClickItem {
        Toast.makeText(this,it.name,Toast.LENGTH_SHORT).show()
        //data update
        edName.setText(it.name)
        edEmail.setText(it.email)
        edBuyAmount.setText(it.buyamount)
        edUseAmount.setText(it.useamount)
        std = it
    }
    adapter?.setOnClickDeleteItem{
        deleteStudent(it.id)

    }
}

private fun deleteStudent(id:Int){
    val builder = AlertDialog.Builder(this)
    builder.setMessage("do you want to delete?")
    builder.setCancelable(true)
    builder.setNegativeButton("no"){dialog, _ ->
        dialog.dismiss()
    }
    builder.setPositiveButton("yes"){dialog, _ ->
        sqLiteHelper.deleteStudentById(id)
        getStudents()
        dialog.dismiss()
    }

    val alert = builder.create()
    alert.show()
}

private fun updateStudent(){
    val name = edName.text.toString()
    val email = edEmail.text.toString()
    val buyAmount = edBuyAmount.text.toString().toInt()
    val useAmount = edUseAmount.text.toString().toInt()
    //Check record not changed
    if(name == std?.name && email == std?.email && buyAmount == std?.buyamount && useAmount == std?.useamount){
        Toast.makeText(this,"Data wasnt updated",Toast.LENGTH_SHORT).show()
        return
    }

    if(std == null) return
    val std = StudentModel(id=std!!.id,name = name,email = email, buyamount = buyAmount, useamount = useAmount )
    val status = sqLiteHelper.updateStudent(std)
    if(status > -1){
        clearEditText()
        getStudents()
    }else{
        Toast.makeText(this,"error",Toast.LENGTH_SHORT).show()
    }


}
private fun getStudents(){
    val stdList = sqLiteHelper.getAllStudent()
    Log.e("ok","${stdList.size}")

    adapter?.addItems(stdList)
}
private fun addStudent(){
    val name = edName.text.toString()
    val email = edEmail.text.toString()
    val buyAmount = edBuyAmount.text.toString().toInt()
    val useAmount = edUseAmount.text.toString().toInt()

    if(name.isEmpty()||email.isEmpty()|| buyAmount.toString().isEmpty() ||useAmount.toString().isEmpty()){
        Toast.makeText(this,"enter data",Toast.LENGTH_SHORT).show()
    }else{
        val std = StudentModel(name = name, email=email, buyamount=buyAmount, useamount=useAmount)
        val status = sqLiteHelper.insertStudent(std)
        //Check Insert success or not success
        if(status > -2){
            Toast.makeText(this,"added data",Toast.LENGTH_SHORT).show()
            clearEditText()
        }else{
            Toast.makeText(this,"data is not found。",Toast.LENGTH_SHORT).show()
        }
    }
}
private fun clearEditText(){
    edName.setText("")
    edEmail.setText("")
    edBuyAmount.setText("")
    edUseAmount.setText("")
    edName.requestFocus()
}
private fun initRecyclerView(){
    recyclerView.layoutManager=LinearLayoutManager(this)
    adapter = StudentAdapter()
    recyclerView.adapter=adapter
}
private fun initView(){
    edName = findViewById(R.id.edName)
    edEmail = findViewById(R.id.edEmail)
    edBuyAmount=findViewById(R.id.edBuyAmount)
    edUseAmount=findViewById(R.id.edUseAmount)
    btnAdd = findViewById(R.id.btnAdd)
    btnView = findViewById(R.id.btnView)
    btnUpdate=findViewById(R.id.btnUpdate)
    recyclerView=findViewById(R.id.recyclerView)

}

}

记录适配器class

class StudentAdapter: RecyclerView.Adapter<StudentAdapter.StudentViewHolder>() { private var stdList: ArrayList<StudentModel> = ArrayList() private var onClickItem: ((StudentModel) -> Unit)?=null private var onClickDeleteItem: ((StudentModel) -> Unit)?=null

fun addItems(items: ArrayList<StudentModel>){
    this.stdList=items
    notifyDataSetChanged()
}
fun setOnClickItem(callback:(StudentModel)->Unit){
    this.onClickItem = callback
}
fun setOnClickDeleteItem(callback: (StudentModel) -> Unit){
    this.onClickDeleteItem = callback
}

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int)= StudentViewHolder (
    LayoutInflater.from(parent.context).inflate(R.layout.card_items_rec,parent,false)
)

override fun onBindViewHolder(holder: StudentViewHolder, position: Int) {
    val std = stdList[position]
    holder.bindView(std)
    holder.itemView.setOnClickListener{onClickItem?.invoke(std)}
    holder.btnDelete.setOnClickListener{onClickDeleteItem?.invoke(std)}
}

override fun getItemCount(): Int {
    return stdList.size
}
class StudentViewHolder(var view: View):RecyclerView.ViewHolder(view){
    private var id = view.findViewById<TextView>(R.id.tvId)
    private var name = view.findViewById<TextView>(R.id.tvName)
    private var email = view.findViewById<TextView>(R.id.tvEmail)
    private var buyAmount = view.findViewById<TextView>(R.id.tvBuyAmount)
    private var useAmount = view.findViewById<TextView>(R.id.tvUseAmount)
    var btnDelete = view.findViewById<TextView>(R.id.deleteBtn)

    fun bindView(std:StudentModel){
        id.text = std.id.toString()
        name.text = std.name
        email.text = std.email
        buyAmount.text = std.buyamount.toString()
        useAmount.text = std.useamount.toString()
    }
}

}

学生数据库class

class SQLiteHelper(context:Context):SQLiteOpenHelper(context,DATABASE_NAME,null,DATABASE_VERSION){ companion object{ private const val DATABASE_VERSION =1 private const val DATABASE_NAME ="student.db" private const val TBL_STUDENT = "tblRecords" private const val ID ="[id]" private const val NAME ="[name]" private const val EMAIL ="[email]" private const val BUYAMOUNT ="[buyamount]" private const val USEAMOUNT ="[useamount]" }

override fun onCreate(db: SQLiteDatabase?) {
    val createTblStudent = ("CREATE TABLE "+ TBL_STUDENT + "("
            + ID + " INTEGER PRIMARY KEY,"+ NAME +" TEXT,"+
            EMAIL +" TEXT,"+ BUYAMOUNT +" INTEGER,"+ USEAMOUNT +" INTEGER"+")")
    db?.execSQL(createTblStudent)
}

override fun onUpgrade(db: SQLiteDatabase?, oldVersion: Int, newVersion: Int) {
    db!!.execSQL("DROP TABLE IF EXISTS $TBL_STUDENT")
    onCreate(db)
}
fun insertStudent(std: StudentModel): Long {
    val db = this.writableDatabase
    val contentValues = ContentValues()
    contentValues.put(ID, std.id)
    contentValues.put(NAME, std.name)
    contentValues.put(EMAIL, std.email)
    contentValues.put(BUYAMOUNT,std.buyamount)
    contentValues.put(USEAMOUNT,std.useamount)

    val success = db.insert(TBL_STUDENT,null,contentValues)
    db.close()
    return success
}
fun getAllStudent():ArrayList<StudentModel>{
    val stdList: ArrayList<StudentModel> = ArrayList()
    val selectQuery = "SELECT * FROM $TBL_STUDENT"
    val db = this.readableDatabase

    val cursor: Cursor?
    try {
        cursor = db.rawQuery(selectQuery,null)
    }catch (e:Exception){
        e.printStackTrace()
        db.execSQL(selectQuery)
        return ArrayList()
    }
    var id: Int
    var name: String
    var email: String
    var buyamount: Int
    var useamount: Int
    if(cursor.moveToFirst()){
        do{
            id = cursor.getInt(cursor.getColumnIndexOrThrow("id"))
            name = cursor.getString(cursor.getColumnIndexOrThrow("name"))
            email = cursor.getString(cursor.getColumnIndexOrThrow("email"))
            buyamount = cursor.getString(cursor.getColumnIndexOrThrow("buyamount")).toInt()
            useamount = cursor.getString(cursor.getColumnIndexOrThrow("useamount")).toInt()
            val std = StudentModel(id = id,name = name,email=email,buyamount=buyamount,useamount=useamount)
            stdList.add(std)
        }while(cursor.moveToNext())
    }
    return stdList
}
fun updateStudent(std: StudentModel):Int{
    val db = this.writableDatabase
    val contentValues = ContentValues()
    contentValues.put(ID,std.id)
    contentValues.put(NAME,std.name)
    contentValues.put(EMAIL,std.email)
    contentValues.put(BUYAMOUNT, std.buyamount)
    contentValues.put(USEAMOUNT,std.useamount)

    val success = db.update(TBL_STUDENT,contentValues,"id="+std.id,null)
    db.close()
    return success
}
fun deleteStudentById(id:Int):Int{
    val db = this.writableDatabase
    val contentValues = ContentValues()

    contentValues.put(ID,id)

    val success = db.delete(TBL_STUDENT,"id=$id",null)
    db.close()
    return success
}

}

学生模型class

package com.example.sqlitedemo import java.util.* data class StudentModel( var id: Int=getAutoId(), var name: String = "", var email: String = "", var buyamount: Int = 0, var useamount: Int=0 ){ companion object{ fun getAutoId():Int{ val random = Random() return random.nextInt(100) } } }

我尝试了所有方法,但仍然不知道哪里出错了。有什么建议或解决方案吗?

抱歉代码布局不一致,我是堆栈溢出的新手。

问题是TextView的setText方法有多个实现,

public final void setText(@StringRes int resid) {
     // ...
}

public final void setText(CharSequence text) {
     // ...
}

而你的student模型的buyamountuseamount是int类型

所以,当你调用TextView的setText时,系统会调用setText(Int)而不是setText(CharSequence)

setText(Int)会使用int参数作为资源id来获取字符串资源。当找不到给定id的资源时,会抛出异常。

要解决此问题,请尝试将 buyamountuseamount 转换为字符串,然后再将它们设置到 TextView。例如,

edBuyAmount.setText("" + it.buyamount)
edUseAmount.setText("" + it.useamount)