我们不喜欢Toast,但我们将其包含在DBHelper类中以了解是否已创建数据库
是,Logcat指向Toast和其他相关活动
第一个错误没有评论吐司
这是错误
Attempt to invoke virtual method 'java.lang.String android.content.Context.getPackageName()' on a null object reference
这是对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")
}
}
}
这是带有TOAST的完整DBHelper
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"
}
}
在DBHelper将数据写入数据库之后,nextActivity会调用DBHelper以查询DEPT,并将使用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)
}
因为我们现在很好奇
问题是如何在非活动类中放置Toast或其他形式的通知?
答案 0 :(得分:5)
我怀疑this.context
可能是罪魁祸首。您不能通过这种方式访问SQLiteOpenHelper的上下文。您可以使用以下代码:
//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()
}
它通过构造函数中的context
码字创建对val
的新引用,而该引用又用于Toast
答案 1 :(得分:0)
这就是为什么他们发明内部类的原因,此代码显示了讨厌的旧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)
}
}
答案 2 :(得分:0)
如果您在Kotlin中使用Toast和insdie RecyclerView.Adapter,则必须像这样调用Toast并使用实例前缀:
class MyViewHolder (view : View) : RecyclerView.ViewHolder(view) {
init {
view.setOnClickListener {
Toast.makeText(view.context, "Your Text", Toast.LENGTH_SHORT).show()
}
}
}
其中view是View类的实例,而context是实现RecyclerView的Adapter类的参数