People are excited about developing Android applications with Kotlin. From new side projects to existing enterprise level Java architectures, Kotlin can improve code quality and readability while reducing lines of code and eliminating entire classes of bugs. Find out why Kotlin is being used by developers at companies like Square, Trello, and Pintrest.
2. Who am I?
• Mobile Developer at Atomic Robot
(Android/iOS)
• Graduated from NKU with Master’s in
Computer Science Dec 2016
• I like hoppy beer and spicy wings
3. What is Kotlin?
Kotlin is a statically typed programming language for the JVM,
Android, and for the browser
Kotlin has 100% interoperability with Java
Created by JetBrains for internal projects and open sourced in
2012
4. Motivation behind Kotlin
Kotlin is a pragmatic programming language for JVM and Android
that combines Object oriented and functional features and is
focused on interoperability, safety, clarity and tooling support
Kotlin works everywhere Java works
6. What are Developers Saying?
“It’s really incredible how much we can pare down without sacrificing readability”
- Christina Lee, Pintrest
(https://youtu.be/xRDqDe4rxkM)
“A data point (for Android devs who are Kotlin-curious): @trello is happily using
@kotlin in production nowadays” - Dan Lew, Trello
(https://twitter.com/danlew42/status/809065097339564032)
“Kotlin makes writing math code almost as nice as C++. Properties and operator
overloading offers many possibilities for swizzling & slicing” - Romain Guy, Google
(https://twitter.com/romainguy/status/812454073232453632)
“Today with IntelliJ’s help I upgraded Rounds from Java to Kotlin. It took 12 hours
to go from 5395 lines of .java to 4924 lines of .kt” - Jesse Wilson, Square
(https://twitter.com/jessewilson/status/803122976321400834)
7. What I want this presentation to be
• I want you to consider trying Kotlin if you haven’t used it
• I want you to use Kotlin more if you have used it
• I want you to find out things Kotlin can do better
• I want you to find out better ways to do things in Kotlin
8. What I don’t want this presentation to be
• A religious war
9. Getting Started
After installing Kotlin, using a Intellij IDEA or Android Studio
with an existing Java project configuring Kotlin is as easy as
telling your IDE to Configure Kotlin
Bring up the action
On Mac: Cmd-Shift-A
On Windows: Ctrl-Shift-A
Begin typing “Configure Kotlin”
11. Getting Started
The easiest way to get started writing Kotlin is to convert Java
Code.
Luckily IntelliJ can do that for us as well.
Bring up the action menu and begin typing “Convert Java to
Kotlin”
16. 1. Nullability as a Type
Java:
String str = "test";
str = null;
str.length(); <- BOOM NPE!
Kotlin:
var str: String = "test"
str = null <- Compiler error!
var str: String? = "test"
str = null
str?.length() <- Perfectly OK!
17. 1. Nullability as a Type
Kotlin allows you to show when Objects can or cannot
be null with a ? following the type
Nullable:
var str: String?
Never Null:
var str: String
18. 1. Nullability as a Type
This type safety turns NullPointerExceptions from
Runtime Exceptions and Crashes to Compiler errors
19. 2. Safe Calls
var str: String? = "test"
str = null
str?.length() <- Why is this OK?
This call is considered “safe” the code following a ? will only
execute if the value is not null at the moment of execution
20. 2. Safe Calls
Turns this Java Pattern:
if (outer.inner != null) {
if (outer.inner.deepInner != null) {
outer.inner.deepInner.doSomething();
}
}
Into this concise Kotlin code:
outer.inner?.deepInner?.doSomething()
21. 3. Data Classes
Let’s make a simple Java Object for a server response
public class ServerResponse {
private String message;
private int statusCode;
private String body;
}
22. 3. Data Classes
public class ServerResponse {
private String message;
private int statusCode;
private String body;
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public int getStatusCode() {
return statusCode;
}
public void setStatusCode(int statusCode) {
this.statusCode = statusCode;
}
public String getBody() {
return body;
}
public void setBody(String body) {
this.body = body;
}
}
Now let’s add our getters and setters
23. 3. Data Classes
public class ServerResponse {
private String message;
private int statusCode;
private String body;
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public int getStatusCode() {
return statusCode;
}
public void setStatusCode(int statusCode) {
this.statusCode = statusCode;
}
public String getBody() {
return body;
}
public void setBody(String body) {
this.body = body;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
ServerResponse that = (ServerResponse) o;
if (statusCode != that.statusCode) return false;
if (message != null ? !message.equals(that.message) : that.message != null) return false;
return body != null ? body.equals(that.body) : that.body == null;
}
@Override
public int hashCode() {
int result = message != null ? message.hashCode() : 0;
result = 31 * result + statusCode;
result = 31 * result + (body != null ? body.hashCode() : 0);
return result;
}
}
How about .equals() and .hashCode()?
24. 3. Data Classes
public class ServerResponse {
private String message;
private int statusCode;
private String body;
public ServerResponse(String message, int statusCode, String body) {
this.message = message;
this.statusCode = statusCode;
this.body = body;
}
public class ServerResponseBuilder {
private String message;
private int statusCode;
private String body;
public ServerResponseBuilder setMessage(String message) {
this.message = message;
return this;
}
public ServerResponseBuilder setStatusCode(int statusCode) {
this.statusCode = statusCode;
return this;
}
public ServerResponseBuilder setBody(String body) {
this.body = body;
return this;
}
public ServerResponse createServerResponse() {
return new ServerResponse(message, statusCode, body);
}
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public int getStatusCode() {
return statusCode;
}
public void setStatusCode(int statusCode) {
this.statusCode = statusCode;
}
public String getBody() {
return body;
}
public void setBody(String body) {
this.body = body;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
ServerResponse that = (ServerResponse) o;
if (statusCode != that.statusCode) return false;
if (message != null ? !message.equals(that.message) : that.message != null) return false;
return body != null ? body.equals(that.body) : that.body == null;
}
@Override
public int hashCode() {
int result = message != null ? message.hashCode() : 0;
result = 31 * result + statusCode;
result = 31 * result + (body != null ? body.hashCode() : 0);
return result;
}
@Override
public String toString() {
return "ServerResponse{" +
"message='" + message + ''' +
", statusCode=" + statusCode +
", body='" + body + ''' +
'}';
}
}
How about a Builder just for fun?
25. 3. Data Classes
Do we really need 90+ lines of code for a POJO with 3 properties?
What if we need to add more properties?
Other projects such as Google’s AutoValue will solve this with
annotations, but Kotlin has a built in type to help this all too
common problem
26. 3. Data Classes
data class ServerResponse(var message: String?,
var statusCode: Int,
var body: String?) {
}
Yep, that’s it.
You get .hashCode(), .equals(), and .toString() for free, as well as
generated getters and setters from Java code
27. 3. Data Classes - Proof!
https://gist.github.com/weverb2/9a4a7bccffe4d4b3bdd99f9153e1b00c
29. 4. Named and Default Params
Changing our data class to the following will allow some cool stuff:
data class ServerResponse(var message: String = "Success",
var statusCode: Int = 200,
var body: String = "Body") {
}
This will allow us to create a ServerResponse object like so:
var serverResponse = ServerResponse()
This will create a ServerResponse with the default values we defined
in our constructor
30. 4. Named and Default Params
Let’s do something more interesting than a default constructor.
var serverResponse = ServerResponse()
var copy = serverResponse.copy() // Deep Copy!
With data classes we just got a deep copy for free! But what if we
want to change something?
var serverResponse = ServerResponse()
var changed = serverResponse.copy(statusCode = 404, message = "Not Found”) // :D
Awesome! We get a basic .toBuilder() implementation as well!
31. 4. Named and Default Params
Java Interop Tip!
If you annotate a Kotlin method with default param values like so:
@JvmOverloads
fun example(str: String = "test", number: Int = 12) {
. . .
}
You’ll get the overloaded method signatures available in Java!
32. 5. Extension Functions
Who loves static Util classes? Not me.
With Kotlin we can define extension functions that allow us to add
functionality to objects without subclassing them
33. 5. Extension Functions
Let’s add a new utility to Android’s View class:
fun View.hideKeyboard() {
val imm = context.getSystemService(Context.INPUT_METHOD_SERVICE)
as InputMethodManager
imm.hideSoftInputFromWindow(this.windowToken, 0)
}
There are a couple new things here, let’s go over what this actually
does
34. 5. Extension Functions
fun View.hideKeyboard() {
val imm = context.getSystemService(Context.INPUT_METHOD_SERVICE)
as InputMethodManager
imm.hideSoftInputFromWindow(this.windowToken, 0)
}
Defining a function with View. in front of the function name means
anything that is a View can now call this method
35. 5. Extension Functions
fun View.hideKeyboard() {
val imm = context.getSystemService(Context.INPUT_METHOD_SERVICE)
as InputMethodManager
imm.hideSoftInputFromWindow(this.windowToken, 0)
}
The reserved keyword as will cast the object returned from
getSystemService to InputMethodManager
36. 5. Extension Functions
The Kotlin stdlib takes advantage of extension functions to add
functionality to Java Library objects
37. 6. String Interpolation
fun sayHello(name: String) {
print("Hello $name!")
}
fun printJobTitle(job: JobDetail) {
print("Hello ${job.jobTitle}!")
}
fun printOrNull(nullable: String?) {
print("Hello ${nullable ?: "Whoops!"}!")
}
Using $ allows you to avoid format strings and StringBuilders. You
can execute code inside the string being built with ${}
38. 7. Developer Happiness
Kotlin is fun to write
Bad pun aside, Kotlin is an extremely enjoyable language that makes
mundane tasks a breeze and offers interesting solutions to common
problems we all have, especially while writing Android applications
Kotlin removes a lot of ceremony and worry to allow me to focus on
solving problems rather than fighting my language
39. 7. Developer Happiness
Context Switching:
- From my experience it is very easy to go from Java back to Kotlin
and vice versa
- What is more surprising to me is when switching between a Kotlin
Android and a Swift iOS project requires much less thought switching
due to their similar paradigms
41. Pain Points
Static methods and variables are not a feature of Kotlin. You may
use “static like” functionality through companion objects
The generated code that the Kotlin plugin creates from converting
Java to Kotlin can have some minor issues
Parceler requires odd boilerplate code to squash reflection warnings
for data classes (Setting Serialization type to Serialization.BEAN)
Fields with multiple annotations have odd syntax
@field:[Inject Api("scoping")] lateinit var picasso: Picasso
42. Dex Count
Kotlin does add ~6600 methods to your dex count
Multidex these days is fairly common, and the tooling around it is
much improved
If Multidexing is out of the question for you, I understand, but
Kotlin isn’t just for Android ;)
44. Future Goals
JetBrains lists the following goals for Kotlin:
Constant performance improvements for the Kotlin toolchain (this
includes, for example, incremental compilation in Gradle, that is in
the works now)
JavaScript support (including cross-compilation into both JVM and JS
where possible)
Support generating Java 8 byte code with optimized lambdas, etc
(Java 6 will be actively supported as long as Android users need
it).