非活动班科特林烤面包

时间:2018-10-02 18:38:01

标签: android kotlin

我们不喜欢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或其他形式的通知?

3 个答案:

答案 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类的参数