fbpx

Kotlin for Android Development: My First Impressions from the Experience

Vladimir Ivanov

Vladimir Ivanov

IT copywriter

#Mobile

30 Aug 2016

Reading time:

30 Aug 2016

Being well acquainted with JVM, many developers know there have been many attempts to find a decent replacement for Java. It seemed that Scala could play this role right up until 2011 when JetBrains announced Kotlin. The company released a new programming language as open-source in 2012 and officially issued the 1.0 version in 2016.

Kotlin came as an answer to a boilerplate code in Java and to the slow compilation speed in Scala. Various well-known software development companies use Kotlin for their projects, for example, Telegram, Prezi, Yandex, and others. Thus, it’s becoming increasingly popular among Java developers because of syntax and IDE support. Even the famous Android enthusiast Jake Wharton applies Kotlin in his projects and draws the attention of the Android community to the use of this language.

I decided to try Kotlin in practice in order to see what the hype is about this new language and whether it is a true Java alternative. Consider this article only as a first impression, not a review.

Kotlin: advantages and disadvantages

Developers praise Kotlin for its concise code, safety, and Java interoperability. It’s quite challenging to list all the strengths of the Kotlin language but I’ll try to define the basics.

Strengths

  • Compiles to JVM bytecode or JavaScripts.
  • 100% Java compatibility. It can use all existing Java frameworks and libraries as well as specific modules in the current projects.
  • It’s open source, that’s why if you find a problem, you can easily inform the Kotlin authors about it.
  • Kotlin repository model weighs less than Scala and adding Kotlin in a project equals adding a support library from Google.
  • Begins with Java 6, can use most of Java 7 and several ported elements of Java 8, so you can use it even if you feel it’s complicated to upgrade to a newer JVM.
  • Immutability by default.
  • Higher-Order Functions or features that take functions as parameters.
  • Null Safety – variables cannot take null in Kotlin by default if you don’t indicate it.

If everything is clear about Kotlin’s advantages, the disadvantages are not as obvious.

Weaknesses

  • Kotlin targets Java 6 bytecode and ignores some advances available in Java 8 such as invoke-dynamic.
  • Problems with annotation processing.
  • There are no analogs for macros or compiler plugins that limit the use of convenient Scala macros or plugins like Checker Framework from Java.
  • Using Java and Kotlin together, it’s better to follow specific rules of compatibility.
  • Some finished and tested Android solutions including architectural solutions need to be rewritten because in Kotlin is better to use an alternative approach.
  • The language is very young and it does not find itself in some specific area. Although it works very well both for Android and server-side development.
  • There are no established best practices for solving specific tasks because the language is young.

My favorite Kotlin features

I’d like to pay more attention to the most useful and interesting features of the language that comes to my mind. Kotlin advantageously differs from the other existing languages applied in Android development. Take a look at the following features*:

*The examples are taken from the official documentation.

  • Break, continue, return at labels:
loop@ for (i in 1..100) { 
 for (j in 1..100) { 
 if (...) 
 break@loop 
 } 
}

break is going to be called for an outer not for the inner loop if an operator was called without label @loop.

fun foo() { 
 ints.forEach { 
 if (it == 0) return@forEach 
 print(it) 
 } 
}

return will be called not for a function but for the cycle forEach.

  • Extensions:
fun <T> MutableList<T>.swap(index1: Int, index2: Int) { 
 val tmp = this[index1] // 'this' corresponds to the list 
 this[index1] = this[index2] 
 this[index2] = tmp 
} 
val l = mutableListOf(1, 2, 3) 
l.swap(0, 2)

Extensions are the direct replacement for all the Utils classes.

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

data classes allow avoiding a huge boilerplate while creating model classes. Methods equals()/hashcode() by the fields of the primary constructor as well as toString(), copy(), getters, setters by the other fields will be generated in this type of class. There is a similar solution in Java, but with more inputs.

  • Object declarations:

Here is how Singleton looks like in Kotlin:

object DataProviderManager { 
 fun registerDataProvider(provider: DataProvider) { 
 // ... 
 } 
 val allDataProviders: Collection<DataProvider> 
 get() = // ... 
}

Class entities indicated via object cannot be created, and we have to call them directly:

DataProviderManager.registerDataProvider(...)

Here is how Factory looks like in Kotlin:

class MyClass { 
 companion object Factory { 
 fun create(): MyClass = MyClass() 
 } 
} 
val instance = MyClass.create()

Although a call of these methods looks like a usual call to statistic variable they are the real objects in runtime and they can implement interfaces.

interface Factory<T> { 
 fun create(): T 
} 
class MyClass { 
 companion object : Factory<MyClass> { 
 override fun create(): MyClass = MyClass() 
 } 
}
  • Observable:
import kotlin.properties.Delegates 
class User { 
 var name: String by Delegates.observable("<no name>") { 
 prop, old, new -> 
 println("$old -> $new") 
 } 
} 
fun main(args: Array<String>) { 
 val user = User() 
 user.name = "first" 
 user.name = "second" 
}

Output:
<no name> -> first
first -> second

We can implement an observer this way and watch the changes in objects.

  • Functions with named, default arguments:
fun reformat(str: String, 
 normalizeCase: Boolean = true, 
 upperCaseFirstLetter: Boolean = true, 
 divideByCamelHumps: Boolean = false, 
 wordSeparator: Char = ' ') { 
... 
}

By doing so, it is possible to call the function using just one argument

reformat(str)

or several

reformat(str, wordSeparator = '_')
  • Higher-order functions:
fun <T> lock(lock: Lock, body: () -> T): T { 
 lock.lock() 
 try { 
 return body() 
 } 
 finally { 
 lock.unlock() 
 } 
}

It allows getting functions as arguments and giving them back as an outcome.

  • Null safety:
bob?.department?.head?.name

This line won’t call NPE but only returns null back if one of the fields will be null.

val l = b?.length ?: -1

If the left-side expression is unequal to null, I will write the value length differently, equal to -1.

val aInt: Int? = a as? Int

If a can be converted to Int – aInt = a or the other way to null.

Of course, this list of the most valuable features in Kotlin is not complete at all. However, all the examples show the language’s functionality and can attract developers with beautiful solutions.

Another argument in favor of Kotlin is its documentation. It is very short but capacious and includes illustrative examples. All of this allows developers to start writing code without excessive preparations. If you’d like to learn this programming language in depth, you can take a look at the detailed official documentation on the Kotlin website.

Kotlin in practice

Kotlin is quite a young language but when project tasks require innovative solutions and there is an opportunity to experiment, we try to use its resources in practice.

Here are examples from my personal experience:

fun Context.checkNetwork() { 
 if (!(connectivityManager.activeNetworkInfo?.isConnected ?: true)) throw IllegalStateException("no network") 
}

Kotlin allows extending classes with new functions. If this was implemented in Java, we had to describe a method as static and the call could be not as obvious as in the case of extending the class Context. Here is how the call is implemented in Kotlin:

checkNetwork() 
 
<======> 
 
class CitiesAdapter(val cities : List<City>?, val onClick: (City) -> Unit) : RecyclerView.Adapter<CitiesAdapter.Holder>(){ 
 
 override fun onBindViewHolder(holder: Holder, position: Int) { 
 holder.bind(cities!!.get(position), position == cities.size - 1) 
 } 
 
 override fun onCreateViewHolder(parent: ViewGroup?, viewType: Int): Holder? { 
 return Holder(LayoutInflater.from(parent?.context).inflate(R.layout.item_city, parent, false), onClick) 
 } 
 
 override fun getItemCount(): Int { 
 return cities?.size ?: 0 
 } 
 
 class Holder(view : View, val onClick: (City) -> Unit) : RecyclerView.ViewHolder(view) { 
 
 fun bind(city : City, last : Boolean) { 
 itemView.description.setText(city.name) 
 val serverUrl = itemView.context.getString(R.string.conf_server_url) 
 Picasso.with(itemView.context).load("${serverUrl}${city.imageUrl}").fit().centerCrop().into(itemView.image) 
 itemView.divider.visibility = if (last) View.GONE else View.VISIBLE 
 itemView.setOnClickListener { onClick(city) } 
 } 
 } 
} 
 
<===>

Kotlin: To use or not to use

Less code = less bugs = better results. Every developer knows this. If you compare two classes written for similar tasks in Java and in Kotlin, you’ll see that the code in Kotlin is shorter and more compact than in Java. It’s a big advantage but not a weighty argument.

In general, I’m happy with my experience of coding in Kotlin. This new language seems to be an affordable alternative to Java with nice documentation and sufficiently understandable principles of use. However, it doesn’t support some helpful and convenient tools in comparison to Java. With all that said, I’d recommend you give it a try. If you’re a dedicated Java developer and looking for some new and nonstandard solutions in developing Android apps, Kotlin can be a true discovery for you.

Comments

Filter by

close

TECHNOLOGIES

INDUSTRIES