Using Kotlin KeyValuePair Database / Serialisation of object/ Deserialisation of object /Store class object in sqlite database



Hello Guys, here is the KeyValue database using Kotlin. I have already explained you keyvalue pair database using Java, if you missed it view example Click Here For Demo

Before we start, let's see some usefull information about Kotlin.

1) Difference between (!!) and (?) operator : (!!) operator means it will check whether the object is null or not, If yes then throw NullPointerException. (?) operator will execute code if the object is not null and if object is null then it will safe nullify it means not throwing exception just skip than line of code.

2) Database related stuff can be write in companion object{} like we are using static for data declaration at the top of class in JAVA


companion object {
        private val DB_NAME = "KEYVALUE"
        private val TABLE = "alldata"
        private val KEY = "key"
        private val VALUE = "value"
        private var memTable: Hashtable<String, Any>? = Hashtable()
        private val TABLE_CREATE = "CREATE TABLE $TABLE ($KEY VARCHAR,$VALUE BLOB)"

    }

Let's see step by step example...

STEP : 1 Create layout.xml


<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <TextView
        android:id="@+id/title1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginBottom="8dp"
        android:layout_marginEnd="8dp"
        android:layout_marginStart="8dp"
        android:layout_marginTop="5dp"
        android:gravity="center"
        android:text="Store Object"
        android:textAppearance="@style/Base.TextAppearance.AppCompat.Medium"
        />

    <android.support.design.widget.TextInputLayout
        android:id="@+id/input_name"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginBottom="8dp"
        android:layout_marginEnd="16dp"
        android:layout_marginStart="16dp"
        android:layout_marginTop="16dp">

        <android.support.design.widget.TextInputEditText
            android:id="@+id/edit_name"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:hint="Name" />
    </android.support.design.widget.TextInputLayout>

    <android.support.design.widget.TextInputLayout
        android:id="@+id/input_email"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginBottom="8dp"
        android:layout_marginEnd="16dp"
        android:layout_marginStart="16dp"
        android:layout_marginTop="16dp">

        <android.support.design.widget.TextInputEditText
            android:id="@+id/edit_email"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:hint="Email" />
    </android.support.design.widget.TextInputLayout>


    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="10dp"
        android:gravity="center_horizontal"
        android:orientation="horizontal">

        <Button
            android:id="@+id/button_store"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginRight="16dp"
            android:text="Store"
            />

        <Button
            android:id="@+id/button_get"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center_horizontal"
            android:text="Get"
            />
    </LinearLayout>

    <LinearLayout
        android:id="@+id/layout_response"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="16dp"
        android:background="#F5F5F5"
        android:orientation="vertical"
        android:visibility="gone">

        <TextView
            android:id="@+id/title2"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginBottom="8dp"
            android:layout_marginEnd="8dp"
            android:layout_marginStart="8dp"
            android:layout_marginTop="8dp"
            android:gravity="center"
            android:text="Get Object"
            android:textAppearance="@style/Base.TextAppearance.AppCompat.Medium"
            />

        <TextView
            android:id="@+id/text_name"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:padding="5dp" />

        <TextView
            android:id="@+id/text_email"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:padding="5dp" />

        <Button
            android:id="@+id/button_delete"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center_horizontal"
            android:text="Delete"
            style="@style/Base.TextAppearance.AppCompat.Widget.Button.Borderless.Colored"
            android:layout_marginBottom="10dp"/>
    </LinearLayout>


</LinearLayout>

STEP : 2 Create UserDetail.kt (A POJO class)


package modal

import java.io.Serializable

/**
 * Created by chirag on 9/2/18.
 */
class UserDetail: Serializable{
    private final val serialVersionUID = 0L

    private var name: String?= null
    private var email: String?= null

    fun getName(): String? {
        return name
    }

    fun setName(name: String){
        this.name = name
    }
    fun getEmail(): String? {
        return email
    }

    fun setEmail(email: String){
        this.email = email
    }
}

STEP : 3 Create KeyValueStore.kt (A Database class)


package storage

import android.content.ContentValues
import android.content.Context
import android.database.sqlite.SQLiteDatabase
import android.database.sqlite.SQLiteOpenHelper
import android.os.Build
import android.support.annotation.RequiresApi
import java.io.*
import java.util.*

/**
 * Created by chirag on 9/2/18.
 */
class KeyValueStore(context: Context?, name: String?, factory: SQLiteDatabase.CursorFactory?, version: Int) : SQLiteOpenHelper(context, name, factory, version) {

    companion object {
        private val DB_NAME = "KEYVALUE"
        private val TABLE = "alldata"
        private val KEY = "key"
        private val VALUE = "value"
        private var memTable: Hashtable<String, Any>? = Hashtable()
        private val TABLE_CREATE = "CREATE TABLE $TABLE ($KEY VARCHAR,$VALUE BLOB)"

    }

    override fun onCreate(db: SQLiteDatabase?) {
        db!!.execSQL(TABLE_CREATE)
    }

    override fun onUpgrade(db: SQLiteDatabase?, oldVersion: Int, newVersion: Int) {
        TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
    }

    fun <T> getValue(key: String, type: Class<T>): T? {
        val db = this.readableDatabase
        val c = db.rawQuery("SELECT $VALUE FROM $TABLE WHERE $KEY=?;", arrayOf(key))
        var ret = getNullFor(type)
        if (c.moveToNext()) {
            try {
                ret = type.cast(deserializeObject(c.getBlob(c.getColumnIndex(VALUE))))
            } catch (e: Exception) {
                e.printStackTrace()
            }

        }
        c.close()
        return ret
    }

    private fun deserializeObject(bytes: ByteArray?): Any? {
        try {
            val ois = ObjectInputStream(ByteArrayInputStream(bytes))
            return ois.readObject()
        } catch (e: IOException) {
            e.printStackTrace()
        } catch (e: ClassNotFoundException) {
            e.printStackTrace()
        }

        return null
    }

    private fun <T> getNullFor(type: Class<T>): T? {
        if (type == Int::class.java) {
            return 0 as T
        } else if (type == Boolean::class.java) {
            return false as T
        }
        return null
    }

    @RequiresApi(Build.VERSION_CODES.O)
    fun setValue(key: String?, value: Any){

        delete(key)

        var cv: ContentValues?=null

        try {
            cv = ContentValues()
            cv.put(KEY, key)
            cv.put(VALUE, serializeObject(value))
        }catch (e:Exception){
            e.printStackTrace()
        }

        val db: SQLiteDatabase = this.writableDatabase
        db.insert(TABLE, null, cv)
        db.close()

    }

    fun delete(key: String?) {
        var db: SQLiteDatabase ?= null
        try {
            db = this.writableDatabase
            db.execSQL("DELETE FROM $TABLE WHERE $KEY=?", arrayOf(key))
        }catch (e: Exception){
            e.printStackTrace()
        }finally {
            db!!.close()
        }

    }

    fun deleteLike(key: String?){
        var db: SQLiteDatabase ?= null
        try {
            db = this.writableDatabase
            db?.delete(TABLE, KEY+" LIKE ?", arrayOf(key + "%"))
        }catch (e: Exception){
            e.printStackTrace()
        }finally {
            db?.close()
        }
    }

    fun serializeObject(dataObject: Any): ByteArray? {
        val baos = ByteArrayOutputStream()
        try {
            val oos = ObjectOutputStream(baos)
            oos.writeObject(dataObject)
            return baos.toByteArray()
        } catch (e: IOException) {
            e.printStackTrace()
        }

        return null
    }
}

STEP : 4 Create MainActivity.kt (A Activity class)


package com.example.chirag.databaseinkotline

import android.os.Build
import android.os.Bundle
import android.support.annotation.RequiresApi
import android.support.v7.app.AppCompatActivity
import android.text.TextUtils
import android.view.View
import android.widget.*
import modal.UserDetail
import storage.KeyValueStore

class MainActivity : AppCompatActivity() {

    private var keyValueStorage: KeyValueStore? = null
    private var btnStore: Button? = null
    private var btnGet: Button? = null
    private var btnDelete: Button? = null
    private var edtName: EditText? = null
    private var edtEmail: EditText? = null
    private var layoutResponse: LinearLayout? = null
    private var textName: TextView? = null
    private var textEmail: TextView? = null

    @RequiresApi(Build.VERSION_CODES.O)
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        initDatabase()

        initUIControls()

        setListeners()
    }

    private fun initDatabase() {
        /**
         * init class object
         */
        keyValueStorage = KeyValueStore(this, "KEYVALUE", null, 1)

    }

    @RequiresApi(Build.VERSION_CODES.O)
    private fun setListeners() {
        btnStore!!.setOnClickListener { onStore() }
        btnGet!!.setOnClickListener { onGet() }
        btnDelete!!.setOnClickListener { onDelete() }
    }

    private fun onDelete() {
        keyValueStorage!!.deleteLike("UserDetail")
        layoutResponse!!.visibility = View.GONE
        Toast.makeText(this, getString(R.string.label_deleted), Toast.LENGTH_SHORT).show()
    }

    private fun onGet() {
        val userInfo = keyValueStorage!!.getValue("UserDetail", UserDetail::class.java)

        if (userInfo != null) {
            layoutResponse!!.visibility = View.VISIBLE
            textName!!.text = userInfo.getName()
            textEmail!!.text = userInfo.getEmail()

            //edtName!!.setText("")

        } else {
            Toast.makeText(this, "Empty!!", Toast.LENGTH_SHORT).show()
        }
    }

    private fun initUIControls() {
        btnStore = findViewById(R.id.button_store)
        btnGet = findViewById(R.id.button_get)
        btnDelete = findViewById(R.id.button_delete)
        edtName = findViewById(R.id.edit_name)
        edtEmail = findViewById(R.id.edit_email)
        textName = findViewById(R.id.text_name)
        textEmail = findViewById(R.id.text_email)
        layoutResponse = findViewById(R.id.layout_response)
    }

    @RequiresApi(Build.VERSION_CODES.O)
    private fun onStore() {
        if (TextUtils.isEmpty(edtName!!.text.toString())) {
            Toast.makeText(this, "Enter Name", Toast.LENGTH_SHORT).show()
        } else if (TextUtils.isEmpty(edtEmail!!.text.toString())) {
            Toast.makeText(this, "Enter Email", Toast.LENGTH_SHORT).show()
        } else {
            var userInfo: UserDetail? = UserDetail()
            userInfo!!.setName(edtName!!.text.toString())
            userInfo!!.setEmail(edtEmail!!.text.toString())

            keyValueStorage!!.setValue("UserDetail", userInfo)
            Toast.makeText(this, getString(R.string.label_saved), Toast.LENGTH_SHORT).show()
        }
    }
}

:: OUTPUT ::

Comments