Building Android apps with kotlin

Adit Lal
6 min readAug 6, 2017

--

Are you one of those who want to try Kotlin but are not sure whether jump in and try?

This post should help you make your decision — to go all in or if you want to experiment with it first.

  • Kotlin is a concise language that can drastically reduce boilerplate code when done correctly.
  • It focuses on type and null safety while maintaining readability.
  • Kotlin focuses on being lightweight and totally interoperable with Java making it perfect for Android application development
  • Kotlin 1.1 support from Java 1.6 — Most of the legacy Android or Backend Project are supported.

So what do the developers say :

Let’s get started

Few things that help you get started easily

Naming

Java:

private String mSomeString = “Hello world”

Kotlin :

private val someString : String = “Hello world”

val name: String //Final (cant change types)var count: Int //Mutable variable

Use camelcase for naming your variables.

val myVal //kotlinmyClass.getMyVal() //java

The data type is inferred

val a: Int = 100  // Int is redundantval a = 100  // Int is inferredval b: Int// Do somethingb = getResultAsInt()

Void is a plain Java class and has no meaning in Kotlin.

  • Unit → replaces java's void
  • Nothing →'a value that never exists'

Methods / functions in kotlin

fun doSomething()

Class naming convention :

Write a property in its own line

class Person(
public open var firstName: String,
public open var lastName: String,
public open var age:Int
) {}
//Subclass - do thisclass Person(
public open var firstName: String,
public open var lastName: String,
public open var age:Int
) : RealmObject() {}

No need of writing getters and setters

class MyClass {
public var myString: String = ""
}
//You can call
myClassInstance.myString = "Hello"
Log.d("TAG","Value is ${myClassInstance.myString}) //prints Hello

Neat feature : Print variables using string interpolation

$object or ${object.property}

switch() → when(condition)

return when(object) {
is String -> object + "test"
is Number -> String.valueOf(object)
else -> null
}

Nullability — As a rule of thumb, !! should never be used and ? should be used rarely. Theses checks can often be avoided and doing so will provide for a more stable code-base. Whenever possible, objects and properties should be made to be not nullable.

Extensions functions / Utility functions

It lets us to add functions to existing classes and by doing so reducing a lot of boiler plate code ,without having to touch the source code of such classes.

  • Extend an entire class
  • Use added util function

Such functions can be written as you would normally would, and put the name of the class before separated by a point. These functions can be everywhere, usually in an Extensions file which doesn’t even need to contain a class

Example :

class MyClass {

fun doThisAndReturnModified(value:Int) {
return value*2
}
}

Now i need to get the result in a different format but using the above , the method it has cant be modified for new requirement , and let’s say we don’t want to change the entire class by adding a new set of function , we could

MyClass.doThatAndReturnModified(value:Int) {
return value+2
}

Your original class wont be tampered , we just added a new functionality without modifying it

Kotlin Android Extensions

Kotlin Android Extensions is another Kotlin plugin that is included in the regular one, and that will allow to recover views from Activities, Fragments ,Views in an amazing seamless way.

import android.os.Bundle
import android.support.v7.app.AppCompatActivity
import kotlinx.android.synthetic.main.activity_main.*
class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
//tvTitle is a TextView in layout activity_main
tvTitle.text = "Hello Kotlin!!"
}
}
//magic comes from this import
//import kotlinx.android.synthetic.main.activity_main.*

Some nifty examples :

Some learnings on the way :

int → Int

public static final String HOLA ="hola"

converts to

val HOLA: String ="hola" // Kotlin does not know what static is //Betterclass SomeClass {
companion object{
const val HOLA = "hola"
}
//...
}

Lazy initialisation

val person by lazy {
SomeUtil(parameter1, parameter2)
}

this helps to initialise certain code only once upon the first usage of person Object.

Then , there is

lateinit var myCustomIntentObj: CustomObject // wont crash
...
onCreate(...){
myCustomIntentObj = intent.getExtras().get("key") // this init
}

This greatly helps in Dependency injected variables , ex :

@Inject
lateinit var presenter: MyPresenter

When to use lateinit

  • If you’re variable is mutable
  • If you’re sending a object from another component/ screen — ex Intent extras

Kotlin classes can be declared as sealed— to avoid subclassing

// with the sealed keyword, we cannot create subclasses for MyClass
sealed class MyClass {
// ...
}

constructor signifies the declaration of the primary or secondary constructor with params

Note : The primary constructor cannot contain any code. Initialization code can be placed in initializer blocks, which are prefixed with the init keyword:

// (name: String, surname: String)  default constructor signature
class Person(name: String, surname: String?) {

// init block , represents the body of default constructor
init {
Log.d("primary", "Hello");
}

// secondary constructor
// this(name,"") call to default constructor
constructor(name : String):this(name,null){
this.myname = name
}
}

init helps introduce an initializer block for the class that may contain code to execute when class is created.

Data classes

Almost all android apps , we build have some sort of POJO or data classes with accessors methods , we override toString() , hashcode(), and more

Kotlin helps reduce boilerplate

public class User {
private String name;
private int age;

public User(String name, int age) {
this.name = name;
this.age = age;
}

public String getName() {
return name;
}

public int getAge() {
return age;
}

public String component1() {
return name;
}

public int component2() {
return age;
}

public User copy() {
return new User(name, age);
}

public User copy(String newName) {
return new User(newName, age);
}

public User copy(String newName, int newAge) {
return new User(newName, newAge);
}

@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;

User user = (User) o;

if (age != user.age) return false;
return name != null ? name.equals(user.name) : user.name == null;
}

@Override
public int hashCode() {
int result = name != null ? name.hashCode() : 0;
result = 31 * result + age;
return result;
}

@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}

into :

data class User(val name: String, val age: Int)

Data classes simply help avoid writing boilerplate code for a lot of those big Java bean classes / POJO , kotlin’s data classes provide compiler generated equals , hashcode , toString and more

Java Singleton → Kotlin object

object Payment{
val transactions = arrayListOf<Checkouts>()
fun calculateSalary() {
for (trans in transactions) {
... }
}
}

Kotlin does not have

static

Kotlin recommends using top-level functions instead.

public class MyFragment extends Fragment { public static MyFragment newInstance(int a, String b){
Fragment frag = new MyFragment()
Bundle args = new Bundle()
args.putExtra(...)
}
....
}

Kotlin way —

class MyFragment : Fragment() {
companion object {
/**
* new instance pattern for fragment
*/
@JvmStatic
fun newInstance(a:Int, b:String): MyFragment {
val fragment = ActivitiesMainFragment()
val args = Bundle()
args.putInt("key1",a)
args.putString("key2",b)
fragment.arguments = args
return fragment
}
}
...
}

Looping

val myList :ArrayList<Item> = ArrayList()
myList.add()
//...
for(item in myList) {
//item is one Item
item.doStuff()
}

Conclusion

Using the conversion tool in Android Studio will be a great start. However, exploring the language slowly and carefully will result in better code.

Migrating you existing codebase to Kotlin will be fun and difficult at some times , but my advice give the language a try.

Check my slides on introduction to Kotlin —

--

--