Kotlin Meteor: findViewById dead as Dinosaurs

findViewById(int) is an essential and ubiquitous method call that plods in your Activities, Views, Fragments and Adapters. It sometimes goes out of control but can be tamed with projects like Butter Knife, InjectView or Android Annotations. Being verbose and slow, the results should be cached when used frequently and hence the ViewHolder pattern.

Sometimes, the number of lines of code could be as little as a Compsognathus or could grow large and wild like a T-Rex. Check it out for yourself.

Regular Code

private EditText mEmailEditText;
private EditText mPasswordEditText;
private EditText mConfirmPasswordEditText;
private Spinner  mAgeSpinner;
private Spinner  mCountrySpinner;
private Spinner  mStateOrProvinceSpinner;
private CheckBox mIAgreeCheckBox;
private Button   mRegisterButton;

protected void onCreate(Bundle savedInstanceState) {
    super(savedInstanceState);
    setContentView(R.id.activity_register);

    mEmailEditText = (EditText) findViewById(R.id.emailEditText);
    mPasswordEditText = (EditText) findViewById(R.id.passwordEditText);
    mConfirmPasswordEditText = (EditText) findViewById(R.id.confirmPasswordEditText);
    mAgeSpinner = (Spinner) findViewById(R.id.ageSpinner);
    mCountrySpinner = (Spinner) findViewById(R.id.countrySpinner);
    mStateOrProvinceSpinner = (Spinner) findViewById(R.id.stateOrProvinceSpinner);
    mIAgreeCheckBox = (CheckBox) findViewById(R.id.iAgreeCheckBox);
    mRegisterButton = (Button) findViewById(R.id.registerButton);
}

All my hard work can be explained in a simple sentence – obtain references to my views. The problem is mitigated when using a view binding library, but you still need visible field declarations.

Butter Knife

@InjectView(R.id.emailEditText)
EditText mEmailEditText;

@InjectView(R.id.passwordEditText)
EditText mPasswordEditText;

@InjectView(R.id.confirmPasswordEditText)
EditText mConfirmPasswordEditText;

@InjectView(R.id.ageSpinner)
Spinner  mAgeSpinner;

@InjectView(R.id.countrySpinner)
Spinner  mCountrySpinner;

@InjectView(R.id.stateOrProvinceSpinner)
Spinner  mStateOrProvinceSpinner;

@InjectView(R.id.iAgreeCheckBox)
CheckBox mIAgreeCheckBox;

@InjectView(R.id.registerButton)
Button mRegisterButton;

protected void onCreate(Bundle savedInstanceState) {
    super(savedInstanceState);
    setContentView(R.id.activity_register);

    ButterKnife.inject(this);
}

Better, but still not subtle. This is the farthest Java can take you. Kotlin as a language itself could only take you so far.

Edit: Butter Knife doesn’t stop here. It has several other features like listener injections, view lists, resource binding, nullifying view references, etc., If you are still using Java for development, it is your best bet.

With the not so advertised Kotlin Android Extensions by JetBrains, your code will look like this,

Kotlin Android Extensions

import kotlinx.android.synthetic.activity_register.*

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_register)
}

Is that all? Yeah, that’s all of it ūüėČ and I am sober. CHECK. Notice the import statement.

import kotlinx.android.synthetic.<layout>.*

This statement imports all the widgets in the specified layout as properties. These view properties are named after their XML IDs and can be accessed directly. For instance, if you want to set a click listener for the register button. You can do,

registerButton.setOnClickListener(this) // R.id.registerButton

Next Steps

Check out the Getting Started guide to get started with Kotlin for Android Development and the Kotlin Android Extensions post to reap the above mentioned benefits. I like where this is going, what are your thoughts?

How I wrote my first iOS app while learning Kotlin for Android Development

Ever since I read Jake Wharton’s tweet, I’ve been¬†spending a¬†considerable amount of time with Kotlin¬†for Android development. I’m very impressed with the language. It is concise, elegant, easy to pick up, has excellent tooling support and¬†bundles several language features that Java currently lacks. I was even able to deliver a Kotlin presentation (scheduled for an hour, but would have easily gone for 3 hours if it wasn’t for the rumbling stomachs) during the Madras JUG launch event¬†on 31st January (3 days after Jake’s tweet).

Yesterday, a sudden thought of¬†Swift¬†struck me like a thunderbolt (figuratively) when I was about to leave for lunch.¬†I did take a peek at the language when¬†it was first released last year and it¬†had a resemblance to other “modern” programming languages. Most importantly, it looked a lot more amicable than its predecessor – Objective-C. I recollected my iOS devs in my dev shop raving about the number of Swift libraries that went live on GitHub on the same day when the language was announced.

Before leaving for lunch, I did my usual – just this one and Googled for “swift quick start” and landed on Ray Wenderlich’s website.¬†At the first glance, Swift looked very familiar. If you were to¬†see¬†both the languages at some place that didn’t provide any context (IDE / APIs / conventions), you¬†might accidently¬†mistake one for the other. Following are my observations.

Semicolons;

Optional in both the languages.

Variable Declaration

Kotlin & Swift

var atomicNumber = 8          // Inferred type
var atomicNumber: Int = 8     // Explicit type declaration

Immutable Variables

Kotlin

val pi = 3.14159265359

Swift

let pi = 3.14159265359

Difference: Swift uses the let keyword for immutable variables.

Optionals / Nullables

Kotlin & Swift

var middleName: String? = "X."

Object Instantiation

Kotlin & Swift

var person = Person()

Functions

Kotlin

fun isDealOk(marketPrice: Double, yourOffering: Double): Boolean {
    return retailerPrice <= yourOffering
}

Swift

func isDealOk(marketPrice: Double, yourOffering: Double) -> Bool {
    return retailerPrice <= yourOffering
}

Difference: Swift uses func keyword for function declarations and the return type is preceded by the -> token.

Function Calls

Kotlin

isDealOk(199.0, 149.99)

Swift

isDealOk(199.0, yourOffering: 149.99)

Difference: Swift requires you to include the parameter name (from the second parameter onwards), when you have more than one parameter in a function.

Function Overriding

Kotlin

override fun heal() {
    health += level * healingFactor
}

Swift

override func heal() {
    health += level * healingFactor
}

Difference: Notice the func keyword in Swift.

String Templates

Kotlin

var name = "Kotlin"
println("Hello, ${name}")   // You can also use $name

Swift

var name = "Swift"
println("Hello, \(name)")

Difference: Swift uses the \() syntax for string templating.

Type Checks and Casting

Kotlin & Swift

var isZombie = civilian is Zombie      // Check
var ironMan = tonyStark as IronMan     // Cast

Properties

Kotlin

var delay: Long = 1000L
    get() {
        // Return value from the backing field
    }

    set(value) {
        // Set value to the backing field
    }

Swift

var delay: Long {
    get() {
        // Return a computed value from a different
        // instance property
    }

    set(value) {
        // Set value to a different instance property
    }
}

Difference: Properties in Kotlin and computed properties in Swift serve different purposes. They look syntactically similar, but have slightly different use cases.

Classes

Kotlin

class Martian {
    var name: String = "Z1000"

    constructor(name: String) {
        this.name = name
    }
}

Swift

class Martian {
    var name: String = "Z1000"

    init(name: String) {
        self.name = name
    }
}

Difference: Kotlin has the concept of primary and secondary constructors. Primary constructors are declared in the class header. The above example uses a secondary constructor that was introduced in the M11 release. Notice the use of constructor in Kotlin and init in Swift. Kotlin also has the init keyword, but it is used for initializer blocks.

Inheritance

Kotlin

class Mutant : Human(), Flyable {    // Super class + Trait
}

Swift

class Mutant : Human, Flyable {    // Super class + Protocol
}

Traits & Protocols

Kotlin

trait Flyable {
    var maxSpeed: Float

    fun fly()
    fun land(): Boolean
}

Swift

protocol Flyable {
    var maxSpeed: Float { get set }

    func fly()
    func land() -> Bool
}

Difference: Swift requires you to specify accessor methods for properties using the get and set keywords. The major difference is – trait methods in Kotlin can have implementations, but Swift doesn’t allow method bodies.

Enumerations

Kotlin

enum class Choice {
    ROCK PAPER SCISSORS
}

Swift

enum Choice {
    case ROCK, PAPER, SCISSORS
}

Difference: Absence of the class keyword, presence of case keyword and enum values are separated by commas.

 
I haven’t looked into other Swift features like generics, closures, extensions that have equivalents in Kotlin. I’ll update this post when I do.

So, what did I build?

I built the classic Rock-Paper-Scissors application on iOS using Swift. You pick one, the phone picks one and then we show the outcome. It’s a rather simple application. Here is the screenshot for your viewing pleasure (it’s not that pleasurable though :P)

Rock Paper Scissors iOS App in Swift

Observations

Languages and platforms are entirely different things. Just because someone can work in Java doesn’t mean that he’d be equally good in a dozen of frameworks or language-based platforms that are available in the wild. Play framework, Hadoop, Elastic Search, and Android are all based on Java but require a different set of skills.

One advantage for a Kotlin developer when working with Swift is syntax. Just that. After that, there’s a whole bunch of APIs that you have to master in order to work with Swift on iOS. Then the IDE and toolchain, followed by differences in the UI/UX model, error messages, 3rd party libraries, dependency management and build systems, etc.,

It could be surprisingly difficult to accomplish simple things. I hit a bunker in Swift while creating the app. I wasn’t able to generate a random number within a given range! How cool is that? This is a no-brainer in Java/Kotlin.

Kotlin

val randomIndex = Random().nextInt(CHOICES.length)
val phoneChoice = CHOICES[randomIndex]

Swift

let randomIndex = Int(arc4random_uniform(UInt32(CHOICES.count)))
let phoneChoice = CHOICES[randomIndex]

 
It took me over 15 minutes to figure this out.

Final Words

If you are an Android developer and are looking for productivity and power, you should be learning Kotlin already. With your newly acquired Kotlin skills, it should be encouraging and easy enough to pick up some Swift and iOS skills along the way.

Thank you for reading. Don’t forget to share this post in any of your social media circles if you found it interesting.