Showing posts with label RecyclerView. Show all posts
Showing posts with label RecyclerView. Show all posts

Friday, 14 December 2018

HB Blog 162: View-pager In Android Using Kotlin.

Hey friends, we have seen listview using Kotlin as well as combination of Jetpack Architecture with Kotlin language.

Kotlin Listview Tutorial : - HB Blog 157: Listview In Android Using Kotlin.

Jetpack Architecture : - HB Blog 161: Jetpack Architecture: - Room And Live Data In Kotlin.

In this tutorial, I will show how to create a viewpager with custom adapter in Kotlin Android Application,
Refer the below link for complete sample code:-

Download Sample Code

Have a look on few code snippets,

//activity_main.xml
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:orientation="vertical"
    android:layout_height="match_parent">

    <android.support.design.widget.TabLayout
        android:id="@+id/tablayout_main"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:tabMode="fixed" />


    <android.support.v4.view.ViewPager
        android:id="@+id/viewpager_main"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>

</LinearLayout>

//CustomPagerAdapter.kt
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
package com.harshalbenake.kotlinviewpager.adapter

import android.support.v4.app.Fragment
import android.support.v4.app.FragmentManager
import android.support.v4.app.FragmentPagerAdapter
import com.caressa.libs.leaderboard.ui.fragments.FirstFragment
import com.caressa.libs.leaderboard.ui.fragments.SecondFragment

class CustomPagerAdapter(fragmentManager: FragmentManager) : FragmentPagerAdapter(fragmentManager) {

    override fun getItem(position: Int): Fragment {
        return when (position) {
            0 ->FirstFragment()
            else -> {
                return SecondFragment()
            }
        }
    }

    override fun getCount(): Int {
        return 2
    }

    override fun getPageTitle(position: Int): CharSequence {
        return when (position) {
            0 -> "First"
            else -> {
                return "Second"
            }
        }
    }
}

//MainActivity.kt
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
package com.harshalbenake.kotlinviewpager

import android.os.Bundle
import android.support.v4.app.FragmentActivity
import android.view.MenuItem
import com.harshalbenake.kotlinviewpager.adapter.CustomPagerAdapter
import kotlinx.android.synthetic.main.activity_main.*

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

    override fun onOptionsItemSelected(item: MenuItem) = when (item.itemId) {
        android.R.id.home -> {
            onBackPressed()
            true
        }
        else -> false
    }
    /**
     * init Layout
     */
    private fun initLayout() {
        val fragmentAdapter = CustomPagerAdapter(supportFragmentManager)
        viewpager_main.adapter = fragmentAdapter
        tablayout_main.setupWithViewPager(viewpager_main)
    }
}

Wednesday, 14 November 2018

HB Blog 161: Jetpack Architecture: - Room And Live Data In Kotlin Language.

In my previous, post we saw Listview Using DataBinding In Kotlin Language,

In this post, lets store data using Room And Live data,

Room is an a SQLite object mapping library. Use it to Avoid boilerplate code and easily convert SQLite table data to Java objects. Room provides compile time checks of SQLite statements and can return RxJava, Flowable and LiveData observables.

Manage your app's lifecycle with ease. New lifecycle-aware components help you manage your activity and fragment lifecycles. Survive configuration changes, avoid memory leaks and easily load data into your UI.

Use LiveData to build data objects that notify views when the underlying database changes.

ViewModel Stores UI-related data that isn't destroyed on app rotations.
Refer the below link for complete sample code:-

Download Sample Code

Have a look on few code snippets,
//build.gradle
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation"org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
    implementation 'com.android.support:appcompat-v7:27.0.2'
    implementation 'com.android.support:design:27.0.2'
    implementation "org.jetbrains.kotlin:kotlin-stdlib-jre7:+"
    //room
    implementation 'android.arch.persistence.room:runtime:1.0.0'
    kapt"android.arch.persistence.room:compiler:1.0.0"
    //Lifecycle
    implementation 'android.arch.lifecycle:extensions:1.0.0'
    annotationProcessor "android.arch.lifecycle:compiler:1.0.0"
}

//activity_addperson.xml
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        android:padding="16dp">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="horizontal">

            <TextView
                android:id="@+id/tv_name"
                android:layout_width="150dp"
                android:layout_height="wrap_content"
                android:gravity=""
                android:text="name :"
                android:textAppearance="@style/Base.TextAppearance.AppCompat.Caption" />

            <EditText
                android:id="@+id/et_name"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:hint="enter name"
                android:inputType="text"
                android:textAppearance="@style/Base.TextAppearance.AppCompat.Caption" />
        </LinearLayout>

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="horizontal">

            <TextView
                android:id="@+id/tv_age"
                android:layout_width="150dp"
                android:layout_height="wrap_content"
                android:text="Age :"
                android:textAppearance="@style/Base.TextAppearance.AppCompat.Caption" />

            <EditText
                android:id="@+id/et_age"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:hint="enter age"
                android:inputType="number"
                android:textAppearance="@style/Base.TextAppearance.AppCompat.Caption" />
        </LinearLayout>
    </LinearLayout>
</LinearLayout>

//PersonProfile.kt
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
package com.harshalbenake.kotlinroomlivedata.data.model

import android.arch.persistence.room.ColumnInfo
import android.arch.persistence.room.Entity
import android.arch.persistence.room.PrimaryKey

@Entity(tableName = "personprofile")
data class PersonProfile(
        @PrimaryKey(autoGenerate = true)
        @ColumnInfo(name = "idPerson")
        var idPerson: Int = 0,

        @ColumnInfo(name = "name")
        var name: String = "",

        @ColumnInfo(name = "age")
        var age: String = ""

)

//PersonProfileDAO.kt
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
package com.harshalbenake.kotlinroomlivedata.data

import android.arch.lifecycle.LiveData
import android.arch.persistence.room.*
import com.harshalbenake.kotlinroomlivedata.data.model.PersonProfile

@Dao
interface PersonProfileDAO {
    @Query("select * from personprofile")
    fun getAllPersonProfiles(): LiveData<List<PersonProfile>>

    @Query("select * from personprofile where age>18")
    fun getAllPersonProfilesAbove18(): PersonProfile

    @Query("select * from personprofile where idPerson in (:id)")
    fun getPersonById(id: Int): PersonProfile

    @Query("delete from personprofile")
    fun deleteAllPersonProfiles()

    @Insert(onConflict = OnConflictStrategy.REPLACE)
    fun insertPersonProfiles(personProfile: PersonProfile)

    @Update
    fun updatePersonProfiles(personProfile: PersonProfile)

    @Delete
    fun deletePersonProfiles(personProfile: PersonProfile)
}

//PersonProfileDb.kt
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
package com.harshalbenake.kotlinroomlivedata.data

import android.arch.persistence.room.Database
import android.arch.persistence.room.Room
import android.arch.persistence.room.RoomDatabase
import android.content.Context
import com.harshalbenake.kotlinroomlivedata.data.model.PersonProfile

@Database(entities = [(PersonProfile::class)], version = 1, exportSchema = false)
abstract class PersonProfileDb : RoomDatabase() {
    companion object {
        private var INSTANCE: PersonProfileDb? = null
        fun getDataBase(context: Context): PersonProfileDb {
            if (INSTANCE == null) {
                INSTANCE = Room.databaseBuilder(context.applicationContext, PersonProfileDb::class.java, "personprofile-db")
                        .allowMainThreadQueries().build()
            }
            return INSTANCE as PersonProfileDb
        }
    }

    abstract fun personProfileDAO(): PersonProfileDAO
}

//PersonProfileViewModel.kt
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
package com.harshalbenake.kotlinroomlivedata.viewmodel

import android.app.Application
import android.arch.lifecycle.AndroidViewModel
import android.arch.lifecycle.LiveData
import android.os.AsyncTask
import com.harshalbenake.kotlinroomlivedata.data.model.PersonProfile
import com.harshalbenake.kotlinroomlivedata.data.PersonProfileDb

class PersonProfileViewModel(application: Application) : AndroidViewModel(application) {

    var listPersonProfile: LiveData<List<PersonProfile>>
    private val appDb: PersonProfileDb

    init {
        appDb = PersonProfileDb.getDataBase(this.getApplication())
        listPersonProfile = appDb.personProfileDAO().getAllPersonProfiles()
    }

    fun getListPersonProfiles(): LiveData<List<PersonProfile>> {
        return listPersonProfile
    }

    fun addersonProfile(personProfile: PersonProfile) {
        addAsynTask(appDb).execute(personProfile)
    }


    class addAsynTask(db: PersonProfileDb) : AsyncTask<PersonProfile, Void, Void>() {
        private var personProfileDb = db
        override fun doInBackground(vararg params: PersonProfile): Void? {
            personProfileDb.personProfileDAO().insertPersonProfiles(params[0])
            return null
        }

    }

}

//AddPersonActivity.kt
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
package com.harshalbenake.kotlinroomlivedata.ui

import android.arch.lifecycle.ViewModelProviders
import android.os.Bundle
import android.support.v7.app.AppCompatActivity
import android.view.Menu
import android.view.MenuInflater
import android.view.MenuItem
import android.widget.Toast
import com.harshalbenake.kotlinroomlivedata.R
import com.harshalbenake.kotlinroomlivedata.data.model.PersonProfile
import com.harshalbenake.kotlinroomlivedata.data.PersonProfileDAO
import com.harshalbenake.kotlinroomlivedata.data.PersonProfileDb
import com.harshalbenake.kotlinroomlivedata.viewmodel.PersonProfileViewModel
import kotlinx.android.synthetic.main.activity_addperson.*

//import kotlinx.android.synthetic.main.activity_contact_details.*

class AddPersonActivity : AppCompatActivity() {

    private var personProfileDAO: PersonProfileDAO? = null
    private var personProfileViewModel: PersonProfileViewModel? = null
    private var currentPersonProfile: Int? = null
    private var personProfile: PersonProfile? = null
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_addperson)
        var personProfileDB: PersonProfileDb = PersonProfileDb.getDataBase(this)
        personProfileDAO = personProfileDB.personProfileDAO()
        personProfileViewModel = ViewModelProviders.of(this).get(PersonProfileViewModel::class.java)
        currentPersonProfile = intent.getIntExtra("idPerson", -1)
        if (currentPersonProfile != -1) {
            setTitle("Edit")
            personProfile = personProfileDAO!!.getPersonById(currentPersonProfile!!)
            et_name.setText(personProfile!!.name)
            et_age.setText(personProfile!!.age)
        } else {
            setTitle("Add")
            invalidateOptionsMenu()
        }
    }

    override fun onCreateOptionsMenu(menu: Menu?): Boolean {
        var inflater: MenuInflater = menuInflater
        inflater.inflate(R.menu.menu_items, menu)
        return true
    }

     override fun onOptionsItemSelected(item: MenuItem?): Boolean {
        when (item!!.itemId) {
            R.id.done_item -> {
                if (currentPersonProfile == -1) {
                    menuSavePersonProfile()
                    Toast.makeText(this, "Saved Successfully", Toast.LENGTH_SHORT).show()
                } else {
                    menuUpdatePersonProfile()
                    Toast.makeText(this, "Updated Successfully", Toast.LENGTH_SHORT).show()
                }
                finish()
            }
            R.id.delete_item -> {
                menuDeletePersonProfile()
                Toast.makeText(this, "Deleted Successfully", Toast.LENGTH_SHORT).show()
                finish()
            }
        }
        return super.onOptionsItemSelected(item)
    }

    override fun onPrepareOptionsMenu(menu: Menu): Boolean {
        super.onPrepareOptionsMenu(menu)
        if (currentPersonProfile == -1) {
            menu.findItem(R.id.delete_item).isVisible = false
        }
        return true
    }

    private fun menuSavePersonProfile() {
        var nameContact = et_name.text.toString()
        var numberContact = et_age.text.toString()
        var contact = PersonProfile(0, nameContact, numberContact)
        personProfileViewModel!!.addersonProfile(contact)
    }

    private fun menuDeletePersonProfile() {
        personProfileDAO!!.deletePersonProfiles(personProfile!!)
    }

    private fun menuUpdatePersonProfile() {
        var nameContact = et_name.text.toString()
        var numberContact = et_age.text.toString()
        var contact = PersonProfile(personProfile!!.idPerson, nameContact, numberContact)
        personProfileDAO!!.updatePersonProfiles(contact)
    }

}

//MainActivity.kt
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
package com.harshalbenake.kotlinroomlivedata.ui

import android.arch.lifecycle.Observer
import android.arch.lifecycle.ViewModelProviders
import android.content.Intent
import android.os.Bundle
import android.support.design.widget.FloatingActionButton
import android.support.v7.app.AppCompatActivity
import android.support.v7.widget.LinearLayoutManager
import android.support.v7.widget.RecyclerView
import android.view.Menu
import android.view.MenuItem
import com.harshalbenake.kotlinroomlivedata.R
import com.harshalbenake.kotlinroomlivedata.adapter.PersonProfileAdapter
import com.harshalbenake.kotlinroomlivedata.data.model.PersonProfile
import com.harshalbenake.kotlinroomlivedata.data.PersonProfileDb
import com.harshalbenake.kotlinroomlivedata.viewmodel.PersonProfileViewModel

class MainActivity : AppCompatActivity(), PersonProfileAdapter.OnItemClickListener {

    private var personProfileRecyclerView: RecyclerView? = null
    private var personProfileAdapter: PersonProfileAdapter? = null
    private var personProfileViewModel: PersonProfileViewModel? = null
    private var personProfileDB: PersonProfileDb? = null
    private var fab:FloatingActionButton?= null

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

        initLayout()

        personProfileRecyclerView!!.layoutManager = LinearLayoutManager(this)
        personProfileRecyclerView!!.adapter = personProfileAdapter

        personProfileViewModel!!.getListPersonProfiles().observe(this, Observer { personprofile ->
            personProfileAdapter!!.addContacts(personprofile!!)
        })
        fab!!.setOnClickListener {
            var intent = Intent(applicationContext, AddPersonActivity::class.java)
            startActivity(intent)
        }
    }

    /**
     * init Layout
     */
    fun initLayout(){
        personProfileRecyclerView = findViewById(R.id.recycler_view)
        fab = findViewById(R.id.fab)
        personProfileDB = PersonProfileDb.getDataBase(this)
        personProfileAdapter = PersonProfileAdapter(arrayListOf(), this)
        personProfileViewModel = ViewModelProviders.of(this).get(PersonProfileViewModel::class.java)

    }

    override fun onCreateOptionsMenu(menu: Menu?): Boolean {
        menuInflater.inflate(R.menu.menu_main, menu)
        return true
    }

   override fun onOptionsItemSelected(item: MenuItem): Boolean {
        when (item.itemId) {
            R.id.delete_all_items -> {
                menuDeleteAllPersonProfiles()
            }
        }
        return super.onOptionsItemSelected(item)
    }

    /**
     * menu deletes All Person Profiles
     */
    private fun menuDeleteAllPersonProfiles() {
        personProfileDB!!.personProfileDAO().deleteAllPersonProfiles()
    }
    override fun onItemClick(personProfile: PersonProfile) {
        var intent = Intent(applicationContext, AddPersonActivity::class.java)
        intent.putExtra("idPerson", personProfile.idPerson)
        startActivity(intent)
    }
}

Sunday, 14 October 2018

HB Blog 160: Listview Using DataBinding In Kotlin Language.

Hello guys, we have seen Listview using Kotlin Language in my old posts. You can recall using below link,
HB Blog 157: Listview In Android Using Kotlin.

Also, we saw Databinding library that is part of Jetpack Architecture in my previous blog post, 
HB Blog 159: Jetpack Architecture: - DataBinding.

In this tutorial, let us build listview using databinding in Kotlin language.
Refer the below link for complete sample code:-

Download Sample Code

Have a look on few code snippets,

//build.gradle
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
apply plugin: 'com.android.application'

apply plugin: 'kotlin-android'

apply plugin: 'kotlin-android-extensions'
apply plugin: 'kotlin-kapt'

android {
    compileSdkVersion 26
    buildToolsVersion "27.0.0"
    defaultConfig {
        applicationId "com.harshalbenake.kotlindatabindinglist"
        minSdkVersion 16
        targetSdkVersion 26
        versionCode 1
        versionName "1.0"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
    dataBinding {
        enabled true
    }
}

repositories {
    mavenCentral()
}
dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation 'com.android.support:support-v4:26.1.0'
    implementation 'com.android.support:appcompat-v7:26.1.0'
    implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:+"
    implementation 'com.android.support:recyclerview-v7:26.1.0'
    kapt "com.android.databinding:compiler:3.0.0"
    implementation "org.jetbrains.kotlin:kotlin-stdlib-jre7:+"
}

//rowitempersonprofile.xml
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">

    <data>
        <variable
            name="personprofile"
            type="com.harshalbenake.kotlindatabindinglist.Model.PersonProfile" />
    </data>

    <LinearLayout
        android:layout_width="match_parent"
        android:padding="16dp"
        android:layout_height="wrap_content"
        android:background="@android:drawable/alert_light_frame"
        android:orientation="vertical">

        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:textSize="20sp"
            android:textColor="@android:color/black"
            android:text="@{personprofile.name,default=name}" />

        <TextView
            android:id="@+id/tv_email"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="@{personprofile.email,default=email}" />

        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="@{Integer.toString(personprofile.age),default=0}" />
    </LinearLayout>
</layout>

//PersonProfile.kt
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
package com.harshalbenake.kotlindatabindinglist.Model

/**
 * Used as a layout variable to provide static properties name, emails and age
 */
data class PersonProfile(
        val name: String,
        val email: String,
        val age: Int
)

//PersonProfileAdapter.kt
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
package com.harshalbenake.kotlindatabindinglist.Adapters

import android.databinding.DataBindingUtil
import android.databinding.ViewDataBinding
import android.graphics.Color
import android.support.v7.widget.RecyclerView
import android.view.LayoutInflater
import android.view.ViewGroup
import com.harshalbenake.kotlindatabindinglist.BR
import com.harshalbenake.kotlindatabindinglist.Model.PersonProfile
import com.harshalbenake.kotlindatabindinglist.R
import kotlinx.android.synthetic.main.rowitempersonprofile.view.*

class PersonProfileAdapter(val locallist: List<PersonProfile>) : RecyclerView.Adapter<ViewHolder>() {
    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
        holder.bind(locallist[position])
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
        val layoutInflater = LayoutInflater.from(parent.context)
        val binding: ViewDataBinding = DataBindingUtil.inflate(layoutInflater, R.layout.rowitempersonprofile, parent, false)
        binding.root.tv_email.setTextColor(Color.GRAY)
        return ViewHolder(binding)
    }

    override fun getItemCount(): Int = locallist.size
}

class ViewHolder(val binding: ViewDataBinding) : RecyclerView.ViewHolder(binding.root) {
    fun bind(personprofile: PersonProfile) {
        binding.setVariable(BR.personprofile, personprofile)
        binding.executePendingBindings()
    }
}

//MainActivity.kt
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
package com.harshalbenake.kotlindatabindinglist

import android.os.Bundle
import android.support.v7.app.AppCompatActivity
import android.support.v7.widget.LinearLayoutManager
import android.support.v7.widget.RecyclerView
import com.harshalbenake.kotlindatabindinglist.Adapters.PersonProfileAdapter
import com.harshalbenake.kotlindatabindinglist.Model.PersonProfile

class MainActivity : AppCompatActivity() {

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

        //array variable initialized
        var listItems = arrayListOf<PersonProfile>()
        //arraylist item added
        for (i in 0..10) {
            listItems.add(PersonProfile("Harshal Benake " + i, "harshalbenake" + i + "@gmail.com", 28 + i))
        }

        val recyclerView = findViewById<RecyclerView>(R.id.rv_personprofile)
        recyclerView.layoutManager = LinearLayoutManager(this)
        recyclerView.adapter = PersonProfileAdapter(listItems)
    }
}

Saturday, 1 April 2017

HB Blog 132: Does Your Phone Get Hang? Know Why...

Android phone sometimes gets hang. Does your phone also have same problem? Don't blame OEMs the original equipment manufacturers or Open Handset Alliance for these problems. At least, not completely because Android applications are more responsible for that.
Developers call it as memory leaks in technical terms. Now a days, lot of devices with unlimited memory are coming in the market. But, it is not the SD card memory that we are having scarcity. It is the heap size or the application size.

So what is the heap size?
Android is a full multitasking system so it’s possible to run multiple programs at the same time and obviously each one can’t use all of your device memory. For this reason there is a hard limit on your Android application’s heap size: if your application needs to allocate more memory and you have gone up to that heap size already, you are basically going to get a “out of memory error”.
Heap size limit is device dependent and it has changed a lot over the years, the first Android phone (the G1) has 16MB heap size limit.

Even if you do not plan on using all of this memory, you should use as little as possible to let other applications run without getting them killed. The more applications Android can keep in memory, the faster it will be for the user to switch between his apps. If these memory is allocated more by the application, your phone gets hang and we get a memory leaks issues.

There are many reasons why we face these kind of problems such as large bitmaps, resources, etc. But, most of time it is the context that are kept long-lived references. In Android, a Context is used for many operations but mostly to load and access resources. This is why all the widgets receive a Context parameter in their constructor. In a regular Android application, you usually have two kinds of Context, Activity and Application. It's usually the first one that the developer passes to classes and methods that need a Context. This means that views have a reference to the entire activity and therefore to anything your activity is holding onto, usually the entire View hierarchy and all its resources. Therefore, if you leak the Context ("leak" meaning you keep a reference to it thus preventing the GC from collecting it), you leak a lot of memory. Leaking an entire activity can be really easy if you're not careful.
When the screen orientation changes the system will, by default, destroy the current activity and create a new one while preserving its state. In doing so, Android will reload the application's UI from the resources.

Basically, we can avoid configuration changes by locking screen rotation. But, it is something that wont provide user experience. Such as watching movie in just portrait mode without landscape feature. So we can go for config change attribute in Android Manifest file as below snippet,


1
2
3
<activity android:name=".MyActivity"
    android:configChanges="orientation|keyboardHidden"
android:label="@string/app_name">


also, do not keep long-lived references to a context-activity (a reference to an activity should have the same life cycle as the activity itself), try using the context-application instead of a context-activity.
Avoid non-static inner classes in an activity if you don't control their life cycle, use a static inner class and make a weak reference to the activity inside. And, many more ways to explore time to time while developing Android applications...

Monday, 27 July 2015

HB Blog 85: Creating Material Design Listing Using RecyclerView And CardView.

In this post, I will show how to use card view and recyclerview for listing data items. To create complex lists and cards with material design styles in your apps, you can use the RecyclerView and CardView widgets.

RecyclerView:- A flexible view for providing a limited window into a large data set. 
The RecyclerView widget is a more advanced and flexible version of ListView. This widget is a container for displaying large data sets that can be scrolled very efficiently by maintaining a limited number of views. To use the RecyclerView widget, you have to specify an adapter and a layout manager. To create an adapter, extend the RecyclerView.Adapter class. The details of the implementation depend on the specifics of your dataset and the type of views. A layout manager positions item views inside a RecyclerView and determines when to reuse item views that are no longer visible to the user. To reuse (or recycle) a view, a layout manager may ask the adapter to replace the contents of the view with a different element from the dataset.
CardView:- A FrameLayout with a rounded corner background and shadow. 
The CardView uses elevation property in lollipop version for shadows and falls back to a custom shadow implementation on older platforms. To create a card with a shadow, use the card_view:cardElevation attribute. CardView uses real elevation and dynamic shadows on Android 5.0 (API level 21) and above and falls back to a programmatic shadow implementation on earlier versions.

The RecyclerView and CardView widgets are part of the v7 Support Libraries. To use these widgets in your project, add these Gradle dependencies to your app's module:
dependencies {
    compile 'com.android.support:cardview-v7:21.0.+'
    compile 'com.android.support:recyclerview-v7:21.0.+'
}


Refer the below link for complete sample code:-
Download Sample Code
Download Apk File
Have a look on few code snippets,

RecycleViewActivity.java
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
import android.app.Activity;
import android.os.Bundle;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;


/**
 * Created by harshalbenake on 02/06/15.
 */
public class RecycleViewActivity extends Activity {
     RecyclerView mRecyclerView;
     RecyclerView.Adapter mAdapter;
     RecyclerView.LayoutManager mLayoutManager;
     String[] myDataset;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main_recycle_view);

        mRecyclerView = (RecyclerView) findViewById(R.id.my_recycler_view);
        // use this setting to improve performance if you know that changes
        // in content do not change the layout size of the RecyclerView
        mRecyclerView.setHasFixedSize(true);
        // use a linear layout manager
        mLayoutManager = new LinearLayoutManager(RecycleViewActivity.this);
        mRecyclerView.setLayoutManager(mLayoutManager);

        myDataset = new String[101];
        for (int i = 0; i < 101; i++)
        {
            myDataset[i] = String.format("Harshal Benake: "+i, i);
        }

        // specify an adapter
        mAdapter = new MyAdapter(myDataset);
        mRecyclerView.setAdapter(mAdapter);

    }

    public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> {
        private String[] mDataset;

        // Provide a reference to the views for each data item
        // Complex data items may need more than one view per item, and
        // you provide access to all the views for a data item in a view holder
        public class ViewHolder extends RecyclerView.ViewHolder {
            // each data item is just a string in this case
            public TextView mTextView;
            public ViewHolder(View v) {
                super(v);
                mTextView=(TextView)v.findViewById(R.id.row_textView);
            }
        }

        // Provide a suitable constructor (depends on the kind of dataset)
        public MyAdapter(String[] myDataset) {
            mDataset = myDataset;
        }

        // Create new views (invoked by the layout manager)
        @Override
        public MyAdapter.ViewHolder onCreateViewHolder(ViewGroup parent,
                                                       int viewType) {
            // create a new view
            View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.row_item, parent, false);

            // set the view's size, margins, paddings and layout parameters
            ViewHolder viewHolder = new ViewHolder(view);
            return viewHolder;
        }

        // Replace the contents of a view (invoked by the layout manager)
        @Override
        public void onBindViewHolder(ViewHolder holder, int position) {
            // - get element from your dataset at this position
            // - replace the contents of the view with that element
            holder.mTextView.setText(mDataset[position]);

        }

        // Return the size of your dataset (invoked by the layout manager)
        @Override
        public int getItemCount() {
            return mDataset.length;
        }
    }
}

main_recycle_view.xml
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="match_parent"
    android:layout_height="match_parent">
    <!-- A RecyclerView with some commonly used attributes -->
    <android.support.v7.widget.RecyclerView
        android:id="@+id/my_recycler_view"
        android:scrollbars="none"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>
</LinearLayout>

row_item.xml
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
<android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:card_view="http://schemas.android.com/apk/res-auto"
    android:id="@+id/card_view"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_margin="10dp"
    card_view:cardCornerRadius="4dp">

    <TextView
        android:id="@+id/row_textView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_margin="10dp"
        android:elevation="2dp"
        android:text="New Text" />
</android.support.v7.widget.CardView>

build.gradle
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
apply plugin: 'com.android.application'

android {
    compileSdkVersion 21
    buildToolsVersion "22.0.1"

    defaultConfig {
        applicationId "com.lollipopsupport_as"
        minSdkVersion 15
        targetSdkVersion 21
        versionCode 1
        versionName "1.0"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    compile 'com.android.support:appcompat-v7:21.0.+'
    compile 'com.android.support:cardview-v7:21.0.+'
    compile 'com.android.support:recyclerview-v7:21.0.+'

}