I'm trying to implement int values into my simple sqlite program in Android studio using kotlin language.
I'm a complete beginner when it comes to Kotlin so I first made a sqlite program using only strings but now i want to use Int values.
I managed to make the values int and insert works fine, however when selecting the record, applciation crashes.
Heres the log cat.
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$4.invoke(MainActivity.kt:49)
Error kt 49 and 44 : Relates to
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$4.invoke(MainActivity.kt:44)
at com.example.sqlitedemo.StudentAdapter.onBindViewHolder$lambda-0(StudentAdapter.kt:32)
Error kt:32 relates to
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.access$3600(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)
}
}
Record adapater 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()
}
}
}
StudentDatabase 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
}
}
Student model 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)
}
}
}
I tried everything but still no clue where i went wrong. Any advice or solutions?
Apolgoies for the inconsistent code layout, im new to stack overflow.
CodePudding user response:
The problem is the setText
method of TextView has multiple implementations,
public final void setText(@StringRes int resid) {
// ...
}
public final void setText(CharSequence text) {
// ...
}
And the buyamount
and useamount
of your student model are int type.
So, when you call setText
of TextView, the system will call the setText(Int)
instead of setText(CharSequence)
.
The setText(Int)
will use the int parameter as resources id to get string resource. When the resource of given id not found, the exception will be thrown.
To fix this problem, try to convert the buyamount
and useamount
to string before set them to the TextView. For example,
edBuyAmount.setText("" it.buyamount)
edUseAmount.setText("" it.useamount)