Reputation: 3235
We do not like the Toast but we included it in our DBHelper Class to know if the DB was created
YES the Logcat pointed at the Toast and the other involved Activities
First mistake not commenting out the Toast
Here is the ERROR
Attempt to invoke virtual method 'java.lang.String android.content.Context.getPackageName()' on a null object reference
Here is the call made to the DBHelper
btnSaveItemData.setOnClickListener {
if (etItemData.text.toString().equals("")) {
message("ENTER Item")
etItemData.requestFocus()
return@setOnClickListener
}
if (etItemFK.text.toString().equals("") || etItemFK.text.toString().toInt() == 0) {
message("ENTER foreign key")
etItemFK.requestFocus()
return@setOnClickListener
}
val dbManager = DBHelper(this)
val values = ContentValues()
values.put("item", etItemData.text.toString())
values.put("fkI",Integer.parseInt(etItemFK.text.toString()))
if (idI == 0) {
val mID = dbManager.insertITEM(values)
if (mID > 0) {
tvMsg.setTextColor(Color.RED)
message("ADDED Item successfully")
//Timer().schedule(800){
nextACTIVITY()
//}
} else {
message("Failed to add Item")
}
}
}
And here is the complete DBHelper with TOAST
class DBHelper(context: Context): SQLiteOpenHelper(context,DBHelper.DB_NAME,null,DBHelper.DB_VERSION) {
override fun onCreate(db: SQLiteDatabase?) {
val CREATE_TABLE_DEPT = "CREATE TABLE ${PARENT_TABLE} ($colidD INTEGER PRIMARY KEY,$colDept TEXT,$colPFK INTEGER);"
val CREATE_TABLE_ITEM = "CREATE TABLE ${CHILD_TABLE} ($colidI INTEGER PRIMARY KEY,$colItem TEXT,$colCFK INTEGER);"
db!!.execSQL(CREATE_TABLE_DEPT)
db.execSQL(CREATE_TABLE_ITEM)
Toast.makeText(this.context,"database is created",Toast.LENGTH_LONG).show()
}
override fun onUpgrade(db: SQLiteDatabase?, oldVersion: Int, newVersion: Int) {
val DROP_TABLE_DEPT = "DROP TABLE IF EXISTS $PARENT_TABLE"
val DROP_TABLE_ITEM = "DROP TABLE IF EXISTS $CHILD_TABLE"
db!!.execSQL(DROP_TABLE_DEPT)
db.execSQL(DROP_TABLE_ITEM)
onCreate(db)
}
fun queryDEPT(): List<ModelParent> {
val db = this.writableDatabase
val parentList = ArrayList<ModelParent>()
val selectQuery = "SELECT * FROM ${PARENT_TABLE}"
val cursor = db.rawQuery(selectQuery, null)
if (cursor != null) {
if (cursor.moveToFirst()) {
do {
val contact = ModelParent()
contact.idD = Integer.parseInt(cursor.getString(cursor.getColumnIndex(colidD)))
contact.dept = cursor.getString(cursor.getColumnIndex(colDept))
contact.fkD = Integer.parseInt(cursor.getString(cursor.getColumnIndex(colPFK)))
parentList.add(contact)
} while (cursor.moveToNext())
}
}
cursor.close()
return parentList
}
fun queryITEM(): List<ModelChild> {
val db = this.writableDatabase
val childList = ArrayList<ModelChild>()
val selectQuery = "SELECT * FROM ${CHILD_TABLE}"
val cursor = db.rawQuery(selectQuery, null)
if (cursor != null) {
if (cursor.moveToFirst()) {
do {
val contact = ModelChild()
contact.idI = Integer.parseInt(cursor.getString(cursor.getColumnIndex(colidI)))
contact.item = cursor.getString(cursor.getColumnIndex(colItem))
contact.fkI = Integer.parseInt(cursor.getString(cursor.getColumnIndex(colCFK)))
childList.add(contact)
} while (cursor.moveToNext())
}
}
cursor.close()
return childList
}
fun insertDEPT(values: ContentValues): Long {
val db = this.writableDatabase
val idD = db.insert(PARENT_TABLE, null, values)
return idD
}
fun updateDEPT(values: ContentValues, selection: String, selectionargs: Array<String>):Int{
val db = this.writableDatabase
val dept = db.update(PARENT_TABLE,values,selection,selectionargs)
return dept
}
fun insertITEM(values: ContentValues): Long {
val db = this.writableDatabase
val idI = db.insert(CHILD_TABLE, null, values)
return idI
}
fun updateITEM(values: ContentValues, selection: String, selectionargs: Array<String>): Int {
val db = this.writableDatabase
val count = db.update(CHILD_TABLE, values, selection, selectionargs)
return count
}
fun deleteDEPT(productname: String): Boolean {
var result = false
val query = "SELECT * FROM $PARENT_TABLE WHERE $colDept= \"$productname\""
val db = this.writableDatabase
val cursor = db.rawQuery(query, null)
if (cursor.moveToFirst()) {
val id = Integer.parseInt(cursor.getString(0))
db.delete(PARENT_TABLE, "$colidD = ?", arrayOf(id.toString()))
cursor.close()
result = true
}
db.close()
return result
}
fun deleteITEM(productname: String): Boolean {
var result = false
val query = "SELECT * FROM $CHILD_TABLE WHERE $colItem= \"$productname\""
val db = this.writableDatabase
val cursor = db.rawQuery(query, null)
if (cursor.moveToFirst()) {
val id = Integer.parseInt(cursor.getString(0))
db.delete(CHILD_TABLE, "$colidI = ?", arrayOf(id.toString()))
cursor.close()
result = true
}
db.close()
return result
}
var context: Context? = null
companion object {
private val DB_VERSION = 1
private val DB_NAME = "Kids.db"
private val PARENT_TABLE = "Parent"
private val colidD = "idD"
private val colDept = "Dept"
private val colPFK = "fkD"
private val CHILD_TABLE = "Child"
private val colidI = "idI"
private val colItem = "Item"
private val colCFK = "fkI"
}
}
After the DBHelper writes the Data to the Database the nextActivity makes a call back to the DBHelper to queryDEPT and will display the data with the ViewParentActivity
class ViewParentActivity : AppCompatActivity() {
private var RecyclerAdapter: ParentAdapter? = null
private var recyclerView: RecyclerView? = null
private val db = DBHelper(this)
private var parentList:List<ModelParent> = ArrayList()
private var linearLayoutManager: LinearLayoutManager? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_view_parent)
supportActionBar?.setDisplayHomeAsUpEnabled(true)
initViews()
}// end onCreate
override fun onResume() {
super.onResume()
initDB()
}
// This is ONLY called when Activity is in onResume state
private fun initDB() {
parentList = db.queryDEPT()
if(parentList.isEmpty()){
title = "No Records in DB"
}else{
title = "Parent List"
}
RecyclerAdapter = ParentAdapter(parentList = parentList, context = applicationContext)
(recyclerView as RecyclerView).adapter = RecyclerAdapter
}
private fun initViews() {
recyclerView = this.findViewById(R.id.rvParentView)
// val etDeptFK can not be reasigned ?
//etDeptFK = this.findViewById(R.id.etDeptFK)
RecyclerAdapter = ParentAdapter(parentList = parentList, context = applicationContext)
linearLayoutManager = LinearLayoutManager(applicationContext)
(recyclerView as RecyclerView).layoutManager = linearLayoutManager!!
}
override fun onCreateOptionsMenu(menu: Menu?): Boolean {
menuInflater.inflate(R.menu.menu_main, menu)
return super.onCreateOptionsMenu(menu)
}
override fun onOptionsItemSelected(item: MenuItem?): Boolean {
if (item != null) {
when (item.itemId) {
R.id.addNote -> {
val intent = Intent(this, EnterParentActivity::class.java)
intent.putExtra("FROM","N")// ADD NEW NOTE
startActivity(intent)
}
}
// CODE below manages HOME Button
val id = item.itemId
if (id == android.R.id.home) {
val intent = Intent(this, EnterParentActivity::class.java)
intent.putExtra("FROM","N")// ADD NEW NOTE
startActivity(intent)
}
}
return super.onOptionsItemSelected(item)
}
Because we are curious now
The question is how to place a Toast or some other form of notification in a non Activity Class?
Upvotes: 0
Views: 4423
Reputation: 1225
If you are using Toast in Kotlin and insdie RecyclerView.Adapter, you have to call Toast like this and use instance prefix:
class MyViewHolder (view : View) : RecyclerView.ViewHolder(view) {
init {
view.setOnClickListener {
Toast.makeText(view.context, "Your Text", Toast.LENGTH_SHORT).show()
}
}
}
where view is instance of View class, and context is parameter of Adapter class which implements RecyclerView
Upvotes: 0
Reputation: 6813
I suspect that this.context
might be the culprit. You can not access the context of the SQLiteOpenHelper this way. You can use the following code:
//declare the context as private val property in the constructor see https://kotlinlang.org/docs/reference/classes.html
class DBHelper(private val context: Context):SQLiteOpenHelper(context,DBHelper.DB_NAME,null,DBHelper.DB_VERSION) {
override fun onCreate(db: SQLiteDatabase?) {
val CREATE_TABLE_DEPT = "CREATE TABLE ${DEPT_TABLE} ($colidD INTEGER PRIMARY KEY, $colDept TEXT);"
val CREATE_TABLE_ITEM = "CREATE TABLE ${ITEM_TABLE} ($colidI INTEGER PRIMARY KEY, $colItem TEXT);"
db!!.execSQL(CREATE_TABLE_DEPT)
db.execSQL(CREATE_TABLE_ITEM)
//use the context from the constructor
Toast.makeText(context, " database is created", Toast.LENGTH_LONG).show()
}
It creates a new reference to context
via the val
codeword in the constructor which is in turn used for the Toast
Upvotes: 5
Reputation: 1371
This is why they invented inner class this code shows the nasty old Toast
inner class DatabaseHelper : SQLiteOpenHelper {
var context: Context? = null
constructor(context: Context) : super(context, dbName, null, dbVersion) {
this.context = context
}
override fun onCreate(db: SQLiteDatabase?) {
db!!.execSQL(CREATE_TABLE_SQL)
Toast.makeText(this.context, " database is created", Toast.LENGTH_LONG).show()
}
override fun onUpgrade(db: SQLiteDatabase?, oldVersion: Int, newVersion: Int) {
db!!.execSQL("Drop table IF EXISTS " + dbTable)
}
}
Upvotes: 0