Dauris Little
  • About
  • Blogging Lyf
  • Contact
  • Portfolio
“Never be limited by other people’s limited imaginations.” – Dr. Mae Jamison

Shimmering in Android

Saturday, 15 August 2020 by Dauris

You may or may not  have been aware of certain UX effects within the Facebook application that fires when attempting to retrieve a large amount of data from the network. This library was created by the developers over at Facebook so big shout out to their developer team. This library serves to provide an alternative method of notifying the user that data is being retrieved rather than using the old traditional ProgressBar. There is no surprise that later on Facebook released an open-source library called shimmer which any developer can now implement the shimmer effect.

In this article, we are demonstrating how to execute the shimmer in any android application. We are going to attempt to fetch data from the API using the dependency Fast Android Networking and then display the data in the recycler view. So let’s get to what you’re interested in the code.

Begining the Application

So fire up the Android Studio and create a new project:

  • Select Empty Acivity and select next
    • Name: Application Name
    • Package Name: com.programmingninja.applicationame
    • Language: Kotlin
    • Minimum SDK: API 19
    • “FINISH”

Adding ‘Dependencies’

Add the following dependencies in your app level build.gradle and sync

dependencies {
    implementation fileTree(dir: "libs", include: ["*.jar"])
    implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
    implementation 'androidx.core:core-ktx:1.3.1'
    implementation 'androidx.appcompat:appcompat:1.1.0'
    implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
    implementation 'androidx.recyclerview:recyclerview:1.2.0-alpha05'
    implementation 'com.github.bumptech.glide:glide:4.11.0'
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'androidx.test.ext:junit:1.1.1'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'

    //adding dependencies
    implementation 'com.github.bumptech.glide:glide:4.11.0'
    implementation 'com.facebook.shimmer:shimmer:0.5.0@aar'
    implementation 'com.amitshekhar.android:android-networking:1.0.2'
    implementation 'androidx.recyclerview:recyclerview:1.2.0-alpha05'
}

Within the ‘values’ folder need to add the color code to use in the application. Note adding this background color should be grey or any non-white color since the shimmering effect won’t be visible if you are using a white background. 

<color name="colorGrey">#dddddd</color>

Find the AndroidManifest file and add the following permission within the <manifest></manifest> block

<uses-permission android:name="android.permission.INTERNET" />

To give you some background on the dependencies we add the first is for the media management for loading images. Then we have the Facebook shimmering dependency along with Fast-Android-Networking and using the recyclerview in the project.

Now we are going to create a new layout called layout_item.xml within the layout folder. Please add the following code:

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/item_container">

    <androidx.appcompat.widget.AppCompatImageView
        android:layout_width="60dp"
        android:layout_height="60dp"
        android:id="@+id/img_item_avatar"
        android:padding="4dp"
        app:layout_constraintTop_toBottomOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintBottom_toTopOf="parent" />

    <androidx.appcompat.widget.AppCompatTextView
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:id="@+id/tv_item_id"
        style="@style/TextAppearance.AppCompat.Medium"
        android:layout_marginStart="8dp"
        android:layout_marginTop="4dp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toEndOf="@+id/img_item_avatar"
        app:layout_constraintTop_toTopOf="parent"
        tools:text="Pokemon No" />

    <androidx.appcompat.widget.AppCompatTextView
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:id="@+id/tv_item_name"
        style="@style/TextAppearance.AppCompat.Large"
        android:layout_marginStart="8dp"
        android:layout_marginTop="4dp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="@id/tv_item_id"
        app:layout_constraintTop_toBottomOf="@id/tv_item_id"
        tools:text="Pokemon Name" />

    <androidx.appcompat.widget.AppCompatTextView
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:id="@+id/tv_item_email"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="@id/tv_item_name"
        app:layout_constraintTop_toBottomOf="@id/tv_item_name"
        tools:text="Pokemon Attribute" />
</androidx.constraintlayout.widget.ConstraintLayout>

Now create another layout within the folder called layout_shimmer and then add the following code:

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/shimmer_container"
    android:layout_width="match_parent"
    android:layout_height="60dp">

    <androidx.appcompat.widget.AppCompatImageView
        android:layout_width="60dp"
        android:layout_height="0dp"
        android:id="@+id/img_shim_avatar"
        android:background="@color/colorGrey"
        android:padding="4dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintBottom_toTopOf="parent" />

    <androidx.appcompat.widget.AppCompatTextView
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:id="@+id/tv_shim_id"
        android:background="@color/colorGrey"
        style="@style/TextAppearance.AppCompat.Medium"
        android:layout_marginStart="8dp"
        android:layout_marginTop="4dp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintStart_toEndOf="@+id/img_shim_avatar"
        tools:text="#025" />

    <androidx.appcompat.widget.AppCompatTextView
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:id="@+id/tv_shim_name"
        android:background="@color/colorGrey"
        style="@style/TextAppearance.AppCompat.Large"
        android:layout_marginStart="8dp"
        android:layout_marginTop="4dp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="@+id/tv_shim_id"
        app:layout_constraintTop_toBottomOf="@id/tv_shim_id"
        tools:text="Pikachu" />

    <androidx.appcompat.widget.AppCompatTextView
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:id="@+id/tv_shim_email"
        android:background="@color/colorGrey"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="@+id/tv_shim_name"
        app:layout_constraintTop_toBottomOf="@id/tv_shim_name"
        tools:text="Electric"/>

</androidx.constraintlayout.widget.ConstraintLayout>

Let’s tackle the activity_main.xml in the layout folder and add the below code but before adding let’s provide some context to the XML:

  • We are going to add the ShimmerFrameLayout
    • Within the shimmerframelayout we are going to add some placeholders inside a LinearLayout.
    • Note: that the added placeholder displays multiple times to create the appearance as a list

Then we will add a recyclerview that will display the list of data fetched after executing the network request from the API.

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <com.facebook.shimmer.ShimmerFrameLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:id="@+id/frame_shimmer"
        android:orientation="vertical"
        android:layout_gravity="center">
        <!-- Add 20 Placeholder -->
        <androidx.appcompat.widget.LinearLayoutCompat
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical">
            <include layout="@layout/layout_shimmer" />
            <include layout="@layout/layout_shimmer" />
            <include layout="@layout/layout_shimmer" />
            <include layout="@layout/layout_shimmer" />
            <include layout="@layout/layout_shimmer" />
            <include layout="@layout/layout_shimmer" />
            <include layout="@layout/layout_shimmer" />
            <include layout="@layout/layout_shimmer" />
            <include layout="@layout/layout_shimmer" />
            <include layout="@layout/layout_shimmer" />
            <include layout="@layout/layout_shimmer" />
            <include layout="@layout/layout_shimmer" />
            <include layout="@layout/layout_shimmer" />
            <include layout="@layout/layout_shimmer" />
            <include layout="@layout/layout_shimmer" />
            <include layout="@layout/layout_shimmer" />
            <include layout="@layout/layout_shimmer" />
            <include layout="@layout/layout_shimmer" />
            <include layout="@layout/layout_shimmer" />
            <include layout="@layout/layout_shimmer" />
        </androidx.appcompat.widget.LinearLayoutCompat>
    </com.facebook.shimmer.ShimmerFrameLayout>

    <androidx.recyclerview.widget.RecyclerView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:id="@+id/list_view"
        android:visibility="gone" />

</androidx.constraintlayout.widget.ConstraintLayout>

Create we need to create a data class User: 

import com.google.gson.annotations.SerializedName

data class User (
    @SerializedName("id")
    val id: Int = 0,
    @SerializedName("name")
    val name: String = "",
    @SerializedName("email")
    val email: String = "",
    @SerializedName("avatar")
    val avatar: String = ""
)

Then create an adapater to c

import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.appcompat.view.menu.ActionMenuItemView
import androidx.recyclerview.widget.RecyclerView
import com.bumptech.glide.Glide
import com.programmingninja.crius.R
import kotlinx.android.synthetic.main.layout_item.view.*

class Adapter(private val users: ArrayList<User>) : RecyclerView.Adapter<Adapter.DataViewHolder>() {
    class DataViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
        fun bind(user: User) {
            itemView.tv_item_id.text = "No: ${user.id}"
            itemView.tv_item_name.text = "Hello: ${user.name}"
            itemView.tv_item_email.text = "E: ${user.email}"
            Glide.with(itemView.img_item_avatar.context).load(user.avatar).into(itemView.img_item_avatar)
        }
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) = DataViewHolder(LayoutInflater.from(parent.context).inflate(R.layout.layout_item, parent, false))

    override fun getItemCount(): Int = users.size

    override fun onBindViewHolder(holder: DataViewHolder, position: Int) {
        holder.bind(users[position])
    }

    fun addData(list: List<User>) {
        users.addAll(list)
    }
}

After completing the adapter now select your MainActivity and now time to complete the following kt file:

To keep in mind to start the shimmering effect as soon as the application opens, we add the startShimmer() within the onResume() activity lifecycle and then we stop it with stopShimmer() within the onPause() activity lifecycle method.

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.view.View
import android.widget.Toast
import androidx.recyclerview.widget.DividerItemDecoration
import androidx.recyclerview.widget.LinearLayoutManager
import com.androidnetworking.AndroidNetworking
import com.androidnetworking.error.ANError
import com.androidnetworking.interfaces.ParsedRequestListener
import com.programmingninja.crius.helper.Adapter
import com.programmingninja.crius.helper.User
import kotlinx.android.synthetic.main.activity_main.*

class MainActivity : AppCompatActivity() {

    private lateinit var adapter: Adapter

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        setupUI()
        setAPICall()
    }

    private fun setAPICall() {
        AndroidNetworking.initialize(applicationContext)
        AndroidNetworking.get("https://5e510330f2c0d300147c034c.mockapi.io/users").build()
            .getAsObjectList(User::class.java, object : ParsedRequestListener<List<User>> {
                override fun onResponse(responses: List<User>) {
                    frame_shimmer.stopShimmer()
                    frame_shimmer.visibility = View.GONE
                    list_view.visibility = View.VISIBLE
                    adapter.addData(responses)
                    adapter.notifyDataSetChanged()
                }

                override fun onError(anError: ANError?) {
                    frame_shimmer.visibility = View.GONE
                    Toast.makeText(this@MainActivity, "Something went wrong", Toast.LENGTH_LONG).show()
                }
            })
    }

    private fun setupUI() {
        list_view.layoutManager = LinearLayoutManager(this)
        adapter = Adapter(arrayListOf())
        list_view.addItemDecoration(DividerItemDecoration(list_view.context,(list_view.layoutManager as LinearLayoutManager).orientation))
        list_view.adapter = adapter
    }

    override fun onResume() {
        super.onResume()
        frame_shimmer.startShimmer()
    }

    override fun onPause() {
        frame_shimmer.stopShimmer()
        super.onPause()

    }
}

Take forcus on the following code below to stop the shimmering effect and get the recyclerview to become visible after the network request is executed and data populate in the recyclerview 

override fun onResponse(responses: List<User>) {
    frame_shimmer.stopShimmer()
    frame_shimmer.visibility = View.GONE
    list_view.visibility = View.VISIBLE
    adapter.addData(responses)
    adapter.notifyDataSetChanged()
}

Done

This is all that is needed to fire the application. Hope you enjoyed the read if you need anything else message me for additional assistance.

Happy Learning!!

androidshimmer
Read more
  • Published in Android, Kotlin, Programming Languages
No Comments

Android, SQLite & Kotlin

Friday, 14 August 2020 by Dauris

The name of the database in Android is SQLite. SQLite is the name of the open-source sql database that stores the data in the text file in the device. Here, we will be review and explaining how to execute them with the Kotlin language. 

 

Before diving into the implementation we are going to review a little in details regarding the SQLite class. There are many methods available in the SQLiteDatabase class but the ones we will use are below

MethodDescription
execSQL(): UnitExecutes the SQL query, this is not to be mistaken for a select query
insert(): LongInsert a record into the database
update(): IntFires the update request on a select row
delete():
query(): CursorReturns a cursor over the resultset

HandlerDB

First we are going to create a class that extends to the SQLiteOpenHelper and override its onCreate(), onUpgrade() functions. 

  • CreatePerson – will insert the data by passing the ContentvValues to object to the insert() method
  • UpdatePerson – will update the record by passining the ContentValues to the update() method 
  • DeletePerson – will delete the record by passing the Content
  • ViewPerson – Will create a list adding the records to return to the view
package com.programmingninja.coeus.helper

import android.content.ContentValues
import android.content.Context
import android.database.Cursor
import android.database.sqlite.SQLiteDatabase
import android.database.sqlite.SQLiteException
import android.database.sqlite.SQLiteOpenHelper
import com.programmingninja.coeus.model.PersonModel
import java.time.LocalDateTime

import kotlin.collections.ArrayList

class HandlerDB (context: Context): SQLiteOpenHelper(context, DATABASE_NAME,null,DATABASE_VERSION) {
    companion object {
        private val DATABASE_VERSION = 1
        private val DATABASE_NAME = "ProjectTitan"
        private val TABLE_NAME = "Person"
        private val KEY_ID = "userid"
        private val KEY_USERNAME = "username"
        private val KEY_FIRST_NAME = "firstname"
        private val KEY_LAST_NAME = "lastname"
    }

    override fun onCreate(db: SQLiteDatabase?) {
        //creating the table and columns
        val CREATE_PERSON_TABLE = ("CREATE TABLE $TABLE_NAME (" +
                "$KEY_ID TEXT PRIMARY KEY," +
                "$KEY_USERNAME TEXT," +
                "$KEY_FIRST_NAME TEXT," +
                "$KEY_LAST_NAME TEXT," +
                "timestamp DEFAULT CURRENT_TIMESTAMP)")
        db?.execSQL(CREATE_PERSON_TABLE)
    }

    override fun onUpgrade(db: SQLiteDatabase?, oldVersion: Int, newVersion: Int) {
        db!!.execSQL("DROP TABLE IF EXISTS $TABLE_NAME")
    }

    //method to read data
    fun ViewPerson(): List&lt;PersonModel> {
        val personList:ArrayList&lt;PersonModel> = ArrayList()
        val personCandidates = "SELECT * FROM $TABLE_NAME"
        val db = this.readableDatabase

        val cursor: Cursor?
        try {
            cursor = db.rawQuery(personCandidates, null)
        } catch (e: SQLiteException) {
            db.execSQL(personCandidates)
            return ArrayList()
        }

        var userId: String
        var userName: String
        var fName: String
        var lName: String

        if (cursor.moveToFirst()) {
            do {
                userId = cursor.getString(cursor.getColumnIndex("userid"))
                userName = cursor.getString(cursor.getColumnIndex("username"))
                fName = cursor.getString(cursor.getColumnIndex("firstname"))
                lName = cursor.getString(cursor.getColumnIndex("lastname"))

                val person = PersonModel(userId = userId, userName = userName, fName = fName, lName = lName)
                personList.add(person)
            } while (cursor.moveToNext())
        }
        return personList
    }

    //method to create data
    fun CreatePerson(person: PersonModel): Long {
        val db = this.writableDatabase
        val cv = ContentValues()
        cv.put(KEY_ID, person.userId)
        cv.put(KEY_USERNAME, person.userName)
        cv.put(KEY_FIRST_NAME, person.fName)
        cv.put(KEY_LAST_NAME, person.lName)

        //now insert into the db
        val successfulInsert = db.insert(TABLE_NAME, null, cv)
        db.close()
        return successfulInsert
    }

    //method to update data

    fun UpdatePerson(person: PersonModel): Int {
        val db = this.writableDatabase
        val cv = ContentValues()

        cv.put(KEY_USERNAME, person.userName)
        cv.put(KEY_FIRST_NAME, person.fName)
        cv.put(KEY_LAST_NAME, person.lName)

        val whereClause = "${KEY_ID} = ?"
        val whereArgs = arrayOf(person.userId.toString())

        //attempt to update the record
        val successfulUpdate = db.update(TABLE_NAME, cv, whereClause, whereArgs)
        db.close()
        return successfulUpdate
    }

    //method to delete data
    fun DeletePerson(person: PersonModel): Int {
        val db = this.writableDatabase
        val cv = ContentValues()
        cv.put(KEY_ID, person.userId)

        val whereClause = "${KEY_ID} = ?"
        val whereArg = arrayOf(person.userId.toString())
        //delete candidate
        val successfulDelete = db.delete(TABLE_NAME, whereClause, whereArg)
        db.close()
        return successfulDelete
    }
}

activity_main.xml

Now we are going to work on the main xml layout. This is going to be the main display the user interacts with 

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <androidx.appcompat.widget.LinearLayoutCompat
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_marginBottom="8dp"
        android:layout_marginEnd="8dp"
        android:layout_marginStart="8dp"
        android:layout_marginTop="8dp"
        android:orientation="vertical">

        <TableLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content">
            <TableRow>
                <androidx.appcompat.widget.AppCompatTextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:hint="User ID"
                    android:layout_column="1"/>
                <androidx.appcompat.widget.AppCompatTextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:id="@+id/tv_userId"
                    android:layout_marginLeft="20dp"
                    android:layout_marginStart="20dp"
                    android:width="150dp"/>
            </TableRow>
            <TableRow>
                <androidx.appcompat.widget.AppCompatTextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:hint="Username"
                    android:layout_column="1"/>
                <androidx.appcompat.widget.AppCompatEditText
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:id="@+id/et_userName"
                    android:layout_marginLeft="20dp"
                    android:layout_marginStart="20dp"
                    android:width="150dp"/>
            </TableRow>
            <TableRow>
                <androidx.appcompat.widget.AppCompatTextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:hint="First Name"
                    android:layout_column="1"/>
                <androidx.appcompat.widget.AppCompatEditText
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:id="@+id/et_fName"
                    android:layout_marginLeft="20dp"
                    android:layout_marginStart="20dp"
                    android:width="150dp"/>
            </TableRow>
            <TableRow>
                <androidx.appcompat.widget.AppCompatTextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:hint="Last Name"
                    android:layout_column="1"/>
                <androidx.appcompat.widget.AppCompatEditText
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:id="@+id/et_lName"
                    android:layout_marginLeft="20dp"
                    android:layout_marginStart="20dp"
                    android:width="150dp"/>
            </TableRow>

        </TableLayout>
        <androidx.appcompat.widget.LinearLayoutCompat
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="20dp">

            <ListView
                android:id="@+id/listView"
                android:layout_width="wrap_content"
                android:layout_height="350sp"
                android:longClickable="false" />
        </androidx.appcompat.widget.LinearLayoutCompat>

        <androidx.appcompat.widget.LinearLayoutCompat
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="40dp"
            android:orientation="horizontal"
            android:layout_gravity="center">
            <androidx.appcompat.widget.AppCompatButton
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="View"
                android:id="@+id/pressMe"
                android:onClick="ViewRecord" />
            <androidx.appcompat.widget.AppCompatButton
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Save"
                android:onClick="SaveRecord" />
            <androidx.appcompat.widget.AppCompatButton
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Update"
                android:onClick="UpdateRecord" />
            <androidx.appcompat.widget.AppCompatButton
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Delete"
                android:onClick="DeleteRecord" />
        </androidx.appcompat.widget.LinearLayoutCompat>
    </androidx.appcompat.widget.LinearLayoutCompat>
</androidx.constraintlayout.widget.ConstraintLayout>

Update Person Alert

//creat the layout to display an alertdialog to update request item
<?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:padding="10dp"
    android:orientation="vertical">

    <androidx.appcompat.widget.AppCompatTextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/tv_userId_update"
        android:ems="10"
        android:text="User Id"/>

    <androidx.appcompat.widget.AppCompatEditText
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/et_nameUser_update"
        android:ems="10"
        android:hint="username"/>

    <androidx.appcompat.widget.AppCompatEditText
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/et_firstname_update"
        android:ems="10"
        android:hint="first name"/>

    <androidx.appcompat.widget.AppCompatEditText
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/et_lastname_update"
        android:ems="10"
        android:hint="Last Name"/>
</LinearLayout>

Delete Person Alert

<?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"
    android:padding="10dp">

    <androidx.appcompat.widget.AppCompatTextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/tv_userId_delete"
        android:textSize="20dp"
        android:text="userid" />

    <androidx.appcompat.widget.AppCompatTextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/tv_Name_delete"
        android:textSize="20dp"
        android:text="Name"/>

</LinearLayout>

MainActivity.kt

Now we are focusing on the MainActivity.kt class and we are going to add the following code. In this class, the following functions are going to be added:

  • saveRecord() function which creates the records.
  • viewRecord() function will read all the records and displays them into ListView,
  • updateRecord() function updates the record on the basis on id, and
  • deleteRecord() function deletes the record.

The val db = DatabaseHandler(this) creates the instance of HandlerDB class calls the SQLite database logic.

package com.programmingninja.coeus

import android.content.DialogInterface
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.view.View
import android.widget.AdapterView
import android.widget.EditText
import android.widget.TextView
import android.widget.Toast
import androidx.appcompat.app.AlertDialog
import androidx.appcompat.widget.AppCompatButton
import androidx.appcompat.widget.AppCompatEditText
import androidx.appcompat.widget.AppCompatTextView
import com.programmingninja.coeus.helper.HandlerDB
import com.programmingninja.coeus.helper.MyListadapter
import com.programmingninja.coeus.model.PersonModel
import kotlinx.android.synthetic.main.activity_main.*
import kotlinx.android.synthetic.main.activity_main.view.*
import kotlinx.android.synthetic.main.update_person.*
import java.util.*

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
    }

    //method for reviewing records
    fun ViewRecord (view:View) {
        //creating the instance of the db handler
        val dbHandler = HandlerDB(this)
        //calling the person view
        val person: List<PersonModel> = dbHandler.ViewPerson()
        val personArrayId = Array<String>(person.size){"0"}
        val personArrayUsername = Array<String>(person.size){""}
        val personArrayFirst = Array<String>(person.size){""}
        val personArrayLast = Array<String>(person.size){""}

        for ((index, p) in person.withIndex()) {
            personArrayId[index] = p.userId
            personArrayUsername[index] = p.userName
            personArrayFirst[index] = p.fName
            personArrayLast[index] = p.lName
        }
        //creating custom adapter
        val listAdapter = MyListadapter(this, personArrayId, personArrayUsername, personArrayFirst, personArrayLast)
        listView.adapter = listAdapter
        listView.onItemClickListener = AdapterView.OnItemClickListener {
                adapterView, view, position, id -> 
            //Toast.makeText(applicationContext, "${person[position].userId}",Toast.LENGTH_LONG).show()
            UpdateRecord(person[position].userId)
        }
        listView.onItemLongClickListener = AdapterView.OnItemLongClickListener {
            adapterView, view, position, l ->
            DeleteRecord(person[position].userId, person[position].fName + " " +  person[position].lName)
        }
    }
    //method for deleting a record
     fun DeleteRecord(deleteUserId: String, deleteUserName: String): Boolean {
        //create AlertDisplay
        val alertDialog = AlertDialog.Builder(this)
        val inflater = this.layoutInflater
        val dv = inflater.inflate(R.layout.delete_person, null)

        alertDialog.setView(dv)

        val delete_id = dv.findViewById<AppCompatTextView>(R.id.tv_userId_delete)
        val delete_name = dv.findViewById<AppCompatTextView>(R.id.tv_Name_delete)
        delete_id.text = deleteUserId
        delete_name.text = deleteUserName
        val deletePersonId = delete_id.text

        alertDialog.setTitle("Delete User")
        alertDialog.setMessage("Are you sure you want to delete the user")
        alertDialog.setPositiveButton("Yes, Delete", DialogInterface.OnClickListener { _,_->
            //creating the instance of the handler
            val db = HandlerDB(this)

            //calling the delete method within the handler
            val status = db.DeletePerson(PersonModel(deletePersonId.toString(),"","",""))
            if (status > -1) {
                Toast.makeText(applicationContext, "User has been deleted", Toast.LENGTH_LONG).show()
                val buttonPress = findViewById<AppCompatButton>(R.id.pressMe)
                buttonPress.performClick()
            }
        })

        alertDialog.setNegativeButton("Cancel", DialogInterface.OnClickListener { _, _->

        })
        val b = alertDialog.create()
        b.show()
        return false
    }

    //method for updating a record
     fun UpdateRecord(updatingUser: String) {
        val alertBuilder = AlertDialog.Builder(this)
        val inflater = this.layoutInflater
        val dv = inflater.inflate(R.layout.update_person, null)
        val uPersonUserId = dv.findViewById(R.id.tv_userId_update) as AppCompatTextView
        val uPersonUsername = dv.findViewById(R.id.et_nameUser_update) as AppCompatEditText
        val uPersonFirstName = dv.findViewById<AppCompatEditText>(R.id.et_firstname_update)
        val uPersonLastName = dv.findViewById(R.id.et_lastname_update) as AppCompatEditText
        uPersonUserId.text = updatingUser
        val updatePersonId = uPersonUserId.text
        val updatePersonUsername = uPersonUsername.text
        val updatePersonFirst = uPersonFirstName.text
        val updatePersonLast = uPersonLastName.text

        alertBuilder.setTitle("Update Person")
        alertBuilder.setMessage("Update person data")
        alertBuilder.setPositiveButton("Update", DialogInterface.OnClickListener { _, _->
            //creating an instance of the handler class
            val db = HandlerDB(this)
            if (!updatePersonUsername.isNullOrEmpty() && !updatePersonFirst.isNullOrEmpty() && !updatePersonLast.isNullOrEmpty()) {
                val status = db.UpdatePerson(PersonModel(updatePersonId.toString(), updatePersonUsername.toString(), updatePersonFirst.toString(), updatePersonLast.toString()))

                if (status>-1) {
                    Toast.makeText(applicationContext,"Record Update", Toast.LENGTH_LONG).show()
                    val buttonPress = findViewById<AppCompatButton>(R.id.pressMe)
                    buttonPress.performClick()
                }
            } else {
                Toast.makeText(applicationContext, "username, first and last name required", Toast.LENGTH_LONG).show()
            }
        })

        alertBuilder.setNegativeButton("Cancel", DialogInterface.OnClickListener { di, which ->  })
        alertBuilder.setView(dv)
        val b = alertBuilder.create()
        b.show()
    }

    //method for saving the records
    fun SaveRecord (view: View) {
        val id = UUID.randomUUID()
        val uName = et_userName.text.toString()
        val fName = et_fName.text.toString()
        val lName = et_lName.text.toString()
        val db_handler: HandlerDB = HandlerDB(this)

        if (uName.trim().isNotEmpty() || fName.trim().isNotEmpty() || lName.trim().isNotEmpty()) {
            val status = db_handler.CreatePerson(PersonModel(id.toString(), uName, fName, lName))
            if (status > -1) {
                Toast.makeText(applicationContext, "Person saved", Toast.LENGTH_LONG).show()
                et_userName.setText("")
                et_fName.setText("")
                et_lName.setText("")
            }
        } else {
            Toast.makeText(applicationContext, "Username, First Name and Last Name is required", Toast.LENGTH_LONG).show()
        }
    }
}

PersonModel.kt

package com.programmingninja.coeus.model

class PersonModel (var userId: String, val userName: String, val fName: String, val lName: String) {
}

custom_list.xml

//create a custom row layout for displauong the list items in the ListView
<?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"
    android:id="@+id/lLayout">
    <androidx.appcompat.widget.AppCompatTextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/tv_userId"
        android:text="User Id"
        android:textAppearance="@style/TextAppearance.AppCompat.Medium" />

    <androidx.appcompat.widget.AppCompatTextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/tv_nameU"
        android:text="Username"
        android:textAppearance="@style/TextAppearance.AppCompat.Medium" />

    <androidx.appcompat.widget.AppCompatTextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/tv_nameF"
        android:text="First Name"
        android:textAppearance="@style/TextAppearance.AppCompat.Medium" />

    <androidx.appcompat.widget.AppCompatTextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/tv_nameL"
        android:text="Last Name"
        android:textAppearance="@style/TextAppearance.AppCompat.Medium" />

</LinearLayout>

MyListadapter

//Now, we create the adapter that will populate the data model within the listview
package com.programmingninja.coeus.helper

import android.app.Activity
import android.content.Context
import android.view.View
import android.view.ViewGroup
import android.widget.ArrayAdapter
import androidx.appcompat.widget.AppCompatTextView
import com.programmingninja.coeus.R

class MyListadapter (private val context: Activity, private val idUser: Array&lt;String>, private val nameUser: Array&lt;String>, private val userFirst: Array&lt;String>, private val userLast: Array&lt;String>)
    : ArrayAdapter&lt;String>(context, R.layout.custom_list, nameUser)
{
    override fun getView(position: Int, view: View?, parent: ViewGroup): View {
        val inflater = context.layoutInflater
        val rowView = inflater.inflate(R.layout.custom_list, null, true)

        val idUserTxt =  rowView.findViewById(R.id.tv_userId) as AppCompatTextView
        val nameUserTxt =  rowView.findViewById(R.id.tv_nameU) as AppCompatTextView
        val nameFTxt =  rowView.findViewById(R.id.tv_nameF) as AppCompatTextView
        val nameLTxt =  rowView.findViewById(R.id.tv_nameL) as AppCompatTextView

        idUserTxt.text = "User Id: ${idUser[position]}"
        nameUserTxt.text = "Username: ${nameUser[position]}"
        nameFTxt.text = "First Name: ${userFirst[position]}"
        nameLTxt.text = "Last Name: ${userLast[position]}"
        return rowView
    }
}
androidkotlinsqlite
Read more
  • Published in Android, Kotlin, Programming Languages
No Comments

When over Switch in Kotlin

Thursday, 13 August 2020 by Dauris

Good afternoon Programming Community, I am glad to welcome you to another Kotlin edition. we will look upon the replacement of switch with the when keyword. Firstly, we will look on to some examples of switch and after that, we will look at how the when keyword makes our task or code easier and more understandable. So, let’s get started.

Standard Conditional

if (number == 1) { 
   println("value: 1") 
} else if (nummber == 2) { 
   println("value: 2") 
} else if (number == 3) { 
   println("value: 3") 
} else if (number == 4) { 
   println("value 4") 
} else { 
   println("value greater 5") 
}

A traditional switch is basically just a statement that can substitute a series of simple if/else that make basic checks as displayed above. However it cannot replace all sort of if/else sequences but just those which compare a value with some constant. So, you can only use a switch to perform an action when one specific variable has a certain precise value.

To remove this difficulty, switch-case was introduced, where we pass the variable to be compared with-in the switch statement (in our example, that variable is number) and compare it with various case statements present corresponding to it and do the operation. 

‘switch’

switch (number) {
   case 1:
      println("value: 1")
      break;
   case 2:
      println("value: 2")
      break;
   case 3:
      println("value: 3")
      break;
   case 4:
      println("value: 4")
      break;
   default:
      println("value greater 5")
      break;
}

So, in the above code in order to print the numbers in word, you have to use various conditional statements and this results in a large number of lines of code. Think of a situation when you have to print the words representation of numbers up to 100 or 1000. If you are using conditional statements then you have to use 1000 conditional statements.

In the above code, number is passed in switch statement and cases are used to compare that number. For example, if the number is 1 then case 1 will be executed, if number is 2 then case 2 will be executed and so on. But if the number is not equal to any of the case present then the default block will be executed.

‘when’

when {
   number == 1 -> {
       println("value: 1")
   }
   nummber == 2 -> {
       println("value: 2")
   }
   number == 3 -> {
       println("value: 3")
   }
   number == 4 -> {
       println("value 4")
   }
   else -> {
       println("value greater 5")
   }
}

So, if you are moving from Java to Kotlin, then you will find some changes in the syntax part also. In Java we use switch but in Kotlin, that switch gets converted to when. when is also used for conditional representation but it does the things in a very smarter and easier way. Whenever you are having a number of possibilities then you can use when in your code.

In the above code, like in switch, the number is passed in when and then we compare that number with various options available. In our case, if the number == 1, then “one” will be printed and so on. If more than one match is found then the match that occurs first will be considered only. If no match to the number is found then the else part will be executed.

When in doubt use ‘when’

  • no complex case/break groups, only the condition followed by ->
  • it can group two or more equivalent choices, separating them with a comma

Wrapping Things Up

we learned how to use when in place of switch in Kotlin. We saw that, if we are having a number of possibilities for a particular variable then we can make use of when to handle all the possibilities. Also, we can use when for multiple or more than one choices.

androidandroid developmentkotlinreplace switch with whenswitchswitch vs when
Read more
  • Published in Android, Kotlin, Programming Languages
No Comments

Identifiers & Keywords

Thursday, 06 August 2020 by Dauris
.NET C#

Identifiers C#

Identifiers are the name given to entities such as variables, methods, classes, etc. They are tokens in a program which uniquely identify an element. For example,

int value

From code above value is the variable which is why we call it the identifier. As you will find out later int is consider a “reserved” keyword so should not be used as an identifier unless the prefix @  is present.

Naming Conventions Rule Of Thumb

  • Keywords should not be identifiers
  • No whitespaces
  • Case sensitivity : so firstname Firstname firstName FirstName these are 4 different identifiers
  • Must begin with a letter, underscore or @

Keywords C#

Keywords are predefined sets of reserved words that have special meaning in a program. The meaning of keywords can not be changed, neither can they be directly used as identifiers in a program. For example,

long phoneNumber

From the code above long is considered the keyword whilephoneNumber is the variable or the identifier. In C# long has a special meaning. Keywords such as long, int, bool, string etc are not allowed to be used as identifiers. However when there is a will then we have a way so even though keywords are “reserved” words, tha can be used as indentifiers if you add @  as the prefix long @int   

Note: Though you can use the prefix @ I suggest as good practice and coding etiquette that you do not do that. It is what we call bad “juju”

identifiers in c#keywords in c#
Read more
  • Published in .NET & .NET Core, C#, Programming Languages
No Comments

All rights reserved. 

TOP
This site uses tracking cookies to personalize content and ads. AcceptLearn More