This article covers techniques which make writing Android code in Kotlin efficient and easy. Kotlin is a general-purpose language that compiles to Java bytecode, developed by JetBrains which makes IntelliJ IDE. You can find the code for this article at GitHub
Using Static layout imports in Kotlin
One of the pain points of working with Android is when we want to use one of the views in the activity. We have to use the ‘findViewById()’ function and then type cast it to the appropriate view type. Kotlin takes a different approach: it lets you import all the views in your layout file. For example, suppose we have a layout file as below
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
android:layout_height="match_parent" android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:paddingBottom="@dimen/activity_vertical_margin"
tools:context="com.kotlineffiecienttechniques.MainActivity2">
<TextView android:id="@+id/maintextview"
android:text="@string/hello_world"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</RelativeLayout>
And the activity code which updates the text of the maintextview using static imports:
package com.kotlineffiecienttechniques
import android.support.v7.app.ActionBarActivity
import android.os.Bundle
import android.view.Menu
import android.view.MenuItem
import android.widget.Toast
import kotlinx.android.synthetic.main.activity_main_activity2.*
public class MainActivity2 : ActionBarActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main_activity2)
maintextview.text = "Hello Static Import!"
}
}
In the above code if you see we have ‘statically imported’ all the views using the import statement
import kotlinx.android.synthetic.main.activity_main_activity2.*
Once you have done this you can change the textview as follows:
maintextview.text = "Hello Static Import!"
For the above code to compile, you will have to add the following in the dependencies of your build.gradle
:
dependencies {
compile 'org.jetbrains.anko:anko-sdk21:0.9' // sdk19, sdk21, sdk23 are also available
compile 'org.jetbrains.anko:anko-support-v4:0.9' // In case you need support-v4 bindings
compile 'org.jetbrains.anko:anko-appcompat-v7:0.9' // For appcompat-v7 bindings
}
Apply the plugin:
apply plugin: 'kotlin-android-extensions'
And add the following in buildscript::dependencies
dependencies {
classpath "org.jetbrains.kotlin:kotlin-android-extensions:$kotlin_version"
}
With the above changes if you build and run the app you will see the activity as shown below
Creating POJO classes in Kotlin
In many applications when we want to convert JSON/XML to objects. For this, we need classes which hold the data of the JSON/XML when you are using REST services. Defining such objects (also known as POJO in Java) is more convenient in Kotlin. Suppose you want to define a POJO in Java to represent a book, the code for that would be as follows
public class Book {
private String ISBN;
private float price;
private int quantity;
private String title;
private String description;
public String getISBN() {
return ISBN;
}
public void setISBN(String ISBN) {
this.ISBN = ISBN;
}
public float getPrice() {
return price;
}
public void setPrice(float price) {
this.price = price;
}
public int getQuantity() {
return quantity;
}
public void setQuantity(int quantity) {
this.quantity = quantity;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
}
The same POJO with the same functionality if we want to define in Kotlin can be defined as follows
public class Book {
public var ISBN: String = ""
public var price: Float = 0.toFloat()
public var quantity: Int = 0
public var title: String = ""
public var description: String = ""
}
Or, to make it more concise, it can be defined as a data class as follows.
data class Book2(var ISBN: String, var price: Float, var quantity: Int,
var title: String , var description: String)
This is slightly different from the previous POJO as this has a primary contructor. All parameters need to be passed to the contructor while creating the object. When we define a data class it also adds the methods ‘equals’ , ‘hashCode’ , ‘toString’ . This should be a preferred way to define a POJO in Kotlin.
As you can see above the POJO which was defined in Java in about 50 lines of code. In Kotlin this could be done in 7 lines or in 2 lines using data classes.
Constructors and Inheritance in Kotlin
Kotlin makes it easier to write constructors for your classes. The primary constructor becomes a part of the class header. It follows after the name of the class. So suppose we had a primary constructor for our Book class the code would look as follows
public class Book (var ISBN: String, var price: Float, var quantity: Int,
var title: String , var description: String){
}
The above code defines a primary constructor in which we pass values. The members are initialized with the values.
Now to create an object of the Book class would be as follows
val book1 = Book("123456", 43.0f, 4, "Kotlin for you", "Book on Kotlin")
This removes the boilerplate code of writing separate constructor function. The constructor which just copies the passed parameters into the member variables. Writing such a constructor would be necessary to do if you were using Java to write your Android app.
Inheritance in Kotlin is safer too; all Kotlin classes cannot be extended unless they are defined as open
.
So if you were to extend Book
, then it should be defined as follows
open public class Book (var ISBN: String, var price: Float, var quantity: Int,
var title: String , var description: String){
open fun getShippingPrice():Float {
return price;
}
}
Suppose we have a subclass HardCoverBook
which extends the Book
class, it also overrides the getShippingPrice
function. The code for that would be as follows:
class HardCoverBook(ISBN: String, price: Float, quantity: Int,
title: String , description: String) :
Book(ISBN, price, quantity, title, description) {
override fun getShippingPrice():Float {
return price + 3.0f;
}
}
Using lambda functions in Kotlin
In Android, we often have functions that take one interface as a parameter. In such cases using the Kotlin lambda functions is convenient. See how we can set an onClickListner
on a view
maintextview.setOnClickListener({ view -> Toast.makeText(this, "Showing Toast", Toast.LENGTH_SHORT).show(); })
It is just one line. We don’t even need to specify the type of the parameter view as it can be statically inferred. The equivalent code in Java would be
maintextview.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(this, "Showing Toast", Toast.LENGTH_SHORT).show();
}
});
If we run the program by setting the onClickListener
as per the Kotlin code shown above, you should see the toast as shown below:
Conclusion.
The above are a few examples which help to write concise code in Kotlin for Android. Kotlin is a new language, but is supported by Jetbrains and has good potential. The apk size increases while using Kotlin rather than Java for your Android program. But you might be able to develop code faster in it. So have fun writing your next Android app in Kotlin.