Kotlin on Android – Is it Good for Developers?

After the Android team’s announcement of first class support for Kotlin in the Google I/O keynote in 17th May 2017, Kotlin came to limelight and Android developers started thinking of using Kotlin as the programming language instead of Java (ADT).

Kotlin is a statically-typed programming language developed by Jet Brains that runs on the Java virtual machine (JVM) and also can be compiled to JavaScript source code or uses the LLVM (Low Level Virtual Machine) compiler infrastructure. It is designed to interoperate with Java code and is dependent on Java Class Library, such as the collections framework. Kotlin is a fully supported programming language on Android. Kotlin was written by the same folks who created Android Studio, so its background comes from the mobile industry.

According to jetBrains, following are the reasons to use Kotlin for Android development.

  • Concise – Drastically reduces the amount of boilerplate code. More concise than Java. The code looks clean and easy to understand.
  • Interoperability – Use any existing library on the JVM, as there’s 100% interoperability. Target either the JVM or JavaScript.
  • Safe – Prevents more kinds of errors than Java and avoid entire classes of errors like null pointer exception.
  • Simpler – Way simpler than Scala! For a Java developer, getting started with Kotlin is very easy. The automated Java to Kotlin converter included in the Kotlin plugin helps with the first steps.
  • Performance – Compiles as fast as Java.
  • Small footprints – Kotlin has a very compact runtime library, which can be further reduced through the use of ProGuard. In a real application, the Kotlin runtime adds only a few hundred methods and less than 100K to the size of the .apk file. This means Kotlin adds just a little to .apk file size.

Installation:

The Kotlin plugin is bundled with Android Studio starting from version 3.0. If you use an earlier version, you’ll need to install the Kotlin plugin.

  1. Go to File | Settings | Plugins | Install JetBrains plugin…
  2. Then search for and install Kotlin.
  3. You’ll need to restart the IDE after this completes.
  4. After restarting, Android studio will prompt to configure the Kotlin plugin, select the latest version and click OK.
  5. It will again prompt to sync the gradle, click on sync.

Create a Project or convert existing project:

  1. Create a project normally.
  2. If you have existing code and want to convert in Kotlin then press ctrl+shift+A to find action.
  3. Write convert Java file to Kotlin file and press enter or press the shortcut ctrl+alt+shift+K (this will convert only the current file).

Related: Collaboration, Communication & Connectivity for future-ready organizations, leveraging mobility to create inclusivity, speed and cohesiveness.

4. Or start writing code with Kotlin to call methods written in Java or vice-versa as it is 100% interoperable with Java.

Everything is now ready to build the application and run it on an emulator or device. You can make a release or build an APK of the application and sign it similarly. Kotlin compiler produces byte-code, thus there really is no difference in terms of look and feel of Kotlin applications versus those written in Java.

Nice features of Kotlin:

1. Completely Null safe:

Kotlin completely removes null references by making all datatypes non-nullable (by default) i.e. the compiler won’t let you to use a non-initialized, non-nullable variable. To declare the type as nullable, add a question mark after the type. The compiler will enforce a null-check before accessing the variable. This practice drastically reduces bugs.

You can check if it’s nullable variable in two ways.
(a).The first is a traditional if statement:

if (nullVar != null)
 nullVar.fooboo();

(b).The second is with NULL safe call operator:

nullVar?.fooboo()

For example:

println(nonNullVar.substring(0, 3)) //prints first 3 characters
 println(nullVar?.substring(0, 3)) //prints first 3 characters if the string is not null, prints null otherwise

In some cases programmer may need to test the code if it is null pointer exception or not ,or if he knows the variable is nullable. Then he can use it as the compiler will not check for the null, and if it is null then throws null pointer exception.

println(nullVar!!.substring(0,3)) //prints first 3 characters if the string is not null, crashes with a NullPointerException otherwise.

2. Extension functions:

With an extension function, you can call a function from an object as if it were a part of its class. Kotlin lets you extend a class by adding additional functions to it without manipulating the original definition. Such functions are known as extension functions. The names of these functions should be preceded by the names of the classes they extend.

For example, to add an extension function isTeenager to the Student class, you write the following code outside the class:

fun Student.isTeenager(): Boolean {
 // If age falls in the range
// 13-19 return true
 return age in 13..19 //range
}

In Kotlin, it is compiled to a static function that returns a boolean value. You’d call it as if it were a member function, like

var student = Student()
 student.isTeenager()

as if it is a member function of Student class

3. Data Classes:

We all know that most of our apps are data dependent, we often find ourselves creating model classes to hold data. In Java, this can be very tedious task, generating getter and setter functions for each field. With Kotlin, we can declare the class and all its properties in a single line. The compiler will generate all getter and setter functions, as well as the equality members, toString() and a copy() function.

For example, take this in Java:

public class Student{
 private String name;
 private int age;
 public User(String name, int age) {
 this.name = name;
 this.age = age;
 }
 public void setName(String name) {this.name = name;}
 public String getName() {return this.name;}
 public void setAge(int age) {this.age = age;}
 public int getAge() {return this.age;} 
}

To run the same function in Kotlin, all we need is:

data class Student(var name: String, var age: Int?)

You just have to add data keyword before class keyword and the compiler will take care of generating constructor and getter setters.

4. Singleton: Kotlin doesn’t support static member for class. So, how can we create singleton class in Kotlin?

A thread safe singleton design pattern

In Java if it is like:

public class SomeSingleton {
 private static SomeSingleton instance = null; private SomeSingleton(){
 }
 private synchronized static void createInstance() {
 if (instance == null) {
 instance = new SomeSingleton();
 }
 }
 public static SomeSingleton getInstance() {
 if (instance == null) createInstance();
 return instance;
 }
 }

In Kotlin, it is

object SomeSingleton

The object will be instantiated and its init blocks will be executed lazily upon first access, in a thread-safe way as constructors are private and in case programmer need to initialize something.

With an object declaration, you are getting a safe and efficient singleton class.

object SomeSingleton {
 init {
 println("init called")
 }
 }

5. More features that will save you from some more keystrokes:

(a). Type aliases: Assign an alias to any given type. This is most useful for long types with many generic parameters.

E.g.

typealias MofL = Map<String, List> fun useMap(map: MofL) { }

(b). Clicklistners:

Consider this click listener

In Java:

view.setOnClickListener(new View.OnClickListener() {
 @Override
 public void onClick(View v) {
 // perform click event
 }});

In Kotlin:

view.setOnClickListener { // perform click event }

(c). Semi colons: It is sufficient for Kotlin to sense the end of the statement through a line break. So if you forget to add semicolon at the end of the line, it’s okay!

(d). Constructors: Kotlin’s syntax to create a constructor is very compact. You don’t need to write a constructor separately to initialize member variables but you can add it to the class header only like in the example shown:

class Person(var name: String, var age: Int, var school: String?) {}

If you don’t need to write anything in class then you don’t even need curly braces.

You can add other constructors as well and are known as secondary constructors but you have to delegate it to the primary constructor using this keyword.

constructor(name: String, age: Int, school: String?, email: String) : this(name, age, college) {
 this.email = email
 }

Limitations:

Whenever a new programming language is launched, it takes some time to get into the market. When Kotlin launched, it wasn’t as mature and proper as it is now. Looking at the limitations, as it is new in town, you will not get proper tutorials and learning stuff. Programmers who already worked with Java can pick up Kotlin in a day just by going through the documentation. Kotlin has its own library that will be added on top of Java’s standard library, so file’s build size increases by 100kb and gradle build also takes little more time.

Conclusion:

So you can saw that Kotlin doesn’t have any ground breaking characteristics. While the goal was not to create something revolutionary, but to provide something that is usable and familiar to modern enterprise developers. Kotlin helps us in avoiding some common pitfalls which are common with Java like null references, which increases code efficiency and product quality and it is 100% interoperable with Java.

Using Realm Database in Mobile Applications

Introduction

Realm is an Open Source mobile database, based on the ORM model and a replacement for SQLite. Realm does not use SQLite as its engine and instead it has its own C++ core. Realm stores data in a universal, table-based format by a C++ core. It is cross-platform, supporting Java (in Android only), Android 2.3 i.e. Gingerbread and above, Objective C, Swift, React Native, Xamarin.

Why Realm?

Realm is the fastest database today, with respect to performance, speed and efficiency. One should migrate to Realm because of its unique features:

1.  Zero Copy

Zero Copy means it does not copy results to the cursor window by getting a list of references to the matching objects and one can work directly work with the original objects.

2.  Auto Update UI

Objects in Realm are `live’ and  you don’t have to re-fetch them again.  It can be implemented through realm.addChangeListener

3.  Works on MVCC architecture

`Writes’ does not block `Read’ operations.  Thanks to MVCC architecture, i.e. Multi Version Concurrency Control, the Reader always reads another copy or version of data.

4. Uses a Fluent Interface

To construct multi-clause queries. E.g. Wealm.where(User.class).equalTo(“name”, “John”).or().equalTo(“name”, “Peter”).findAll();

5.  Faster read/writes

Up to 10x speed than SQLite for normal operations.

6.  No Mapping

Results do not need to be mapped to models.

7.  Ease of use

Easy to learn and understand

Installation

Installing Realm as a Gradle plugin requires two steps:

Add the following class path dependency to the project level build.gradle file.

dependencies {
 classpath "io.realm:realm-gradle-plugin:2.2.1"
 }

Apply the realm-android plugin to the top of application level build.gradle.

apply plugin: 'realm-android'

Config class file

Create a class which extends  the application and in it create `write’:

RealmConfiguration realmConfiguration = new RealmConfiguration.Builder(this)
 .name(Realm.DEFAULT_REALM_NAME)
 .schemaVersion(0)
 .deleteRealmIfMigrationNeeded()
 .build();
 Realm.setDefaultConfiguration(realmConfiguration);

Model class file

Create a model class file for Realm.  Unlike others, you need to use this model to create general Java objects too.

Supported field types are: Boolean, Byte, Short, Int, Long, Float, Double, String, Date and byte[].

Public, Private and Protected access specifiers are also supported.

public class User extends RealmObject {
 @PrimaryKey
 private String name;
 @Required
 private int age;
 @Ignore
 private int sessionId;
 @Index
 public String username

// Realm Model Class supports public, protected and private fields as well as custom methods.
// Standard getters & setters generated by your IDE…
}


Relationships

1. One to many

public class Contact extends RealmObject {
 private Email email;
 // Other fields…
 }

2.  Many to many:

public class Contact extends RealmObject {
 public String name;
 public RealmList<Email> emails;
 }

public class Email extends RealmObject {
public String address;
public boolean active;
}

Writes

All write operations (adding, modifying, and removing objects) must be wrapped in write transactions.

// Obtain a Realm instance
 Realm realm = Realm.getDefaultInstance();
 realm.beginTransaction();

//… add or update objects here …

realm.commitTransaction();
or
realm.cancelTransaction();

Creating objects

Every mutator (write, update, delete) operation should be written inside the transaction block.

Either create a new realm object by using User user =  realm.createObject(User.class); and then set data to it by user.setname(“john”) or set email and use the below code, so that you can insert user object with regard to Java or finally you can also copy it to Realm.

User user = new User("John");
 user.setEmail("john@corporation.com");

// Copy the object to Realm. Any further changes must happen on realmUser
realm.beginTransaction();
User realmUser = realm.copyToRealm(user);
realm.commitTransaction();

Queries

To find all users named John or Peter you would write:

No need of Transaction Blocks for queries. Objects can be accessed and queried at any time.

Realm results are ordered.Logical-And is Implicit, Logical-or must be applied explicitly with or().

Results in realm are Auto-updating. So you can provide notifications or update UI whenever realm.addChangeListener get the change.

RealmResults<User> result2 = realm.where(User.class)
 .equalTo("name", "John")
 .or()
 .equalTo("name", "Peter")
 .findAll();

This is a fluent interface most object oriented language uses to built multi-clause queries.

Deletion

// obtain the results of a query

final RealmResults<Dog> results = realm.where(Dog.class).findAll();

// All changes to data must happen in a transaction

realm.executeTransaction(new Realm.Transaction() {

@Override

public void execute(Realm realm) {

// remove single match

results.deleteFirstFromRealm();

results.deleteLastFromRealm();

// remove a single object

Dog dog = results.get(5);

dog.deleteFromRealm();

// Delete all matches

results.deleteAllFromRealm();

}

});

Limitations

Passing Instances across Threads (enforces transaction version isolation).

  1. Updating to newer versions is slightly difficult as several things change in newer versions
  2. There is no support for auto-incrementing field values like ID fields
  3. Not many learning resources are available

References

https://realm.io/docs

Exit mobile version