SlideShare a Scribd company logo
ANDROID 101 - BUILDING A SIMPLE APP
WITH KOTLIN IN 90 MINUTES
KAI KOENIG (@AGENTK)
HELLO
HELLO
I’m Kate!
I’m an { Android Developer | GDG Organiser | Carpenter | 

Backup Mum to all my neighbours cats | …}
Find me on Twitter: @Mistyepd
and I’m Kai!
I’m a { Software Engineer | Pilot | GDG Organiser | 

Gamer | Dad to 1 cat and 3 chickens | … }
Find me on Twitter: @AgentK
HELLO
CODE
https://github.com/TheRealAgentK/
SummerOfTech-Android-2018
AGENDA
▸ What is Kotlin?
▸ Language idioms & concepts
▸ Kotlin and Android
▸ Anko DSL
MORE
GDG WELLINTON
MORE
WELLINGTON.KT
WHAT IS KOTLIN?
WHAT IS KOTLIN?
SOME FUNDAMENTALS
▸ Statically typed programming
language for the JVM and Android
▸ Started as internal language “Project
Kotlin” at Jetbrains in 2010
▸ Now: Open-Source, Apache License
▸ Kotlin SDK plus tool support for IntelliJ,
Android Studio, Eclipse
▸ Named after an island in the Gulf of
Finland
WHAT IS KOTLIN?
MOTIVATION FOR KOTLIN
▸ The Java platform is awesome, but it has its issues:
▸ sometimes tied to backwards/legacy compatibility
▸ can be a very verbose language and produce bloated code
▸ type system has various flaws
▸ Kotlin aims to fix a lot of those issues
▸ compiles to Java 6 byte code therefore caters well for Android runtimes
LANGUAGE IDIOMS &
CONCEPTS
https://www.flickr.com/photos/geraldford/6976818221/
LANGUAGE IDIOMS & CONCEPTS
OVERVIEW
▸ Immutability
▸ String templates & Enum classes
▸ Null safety
▸ Properties and Fields
▸ Type inference and casts
▸ Data classes
▸ Syntactic sugar (loops, ranges etc)
▸ Extension functions
▸ Lambdas
▸ Collection API
▸ Type-safe builders
▸ Java-Kotlin-Interop
LANGUAGE IDIOMS & CONCEPTS
IMMUTABILITY
▸ Built-in support for mutable and
immutable variables, properties and
fields
▸ Keywords var and val
▸ val - immutable (recommended)
▸ var - mutable
▸ Similar concept applies for class
properties, val creates getters, var
creates getters and setters (more later)
val a: Int = 1
val b = 1
val c: Int
c = 1
var x = 23
x += 1
LANGUAGE IDIOMS & CONCEPTS
STRING TEMPLATES & ENUM CLASSES (I)
▸ Kotlin Strings can contain template
expressions
▸ String templates start with a $ character
and
▸ can contain simple references such
as $s, as well as
▸ complex expressions in curly braces: 

${s.length}
val s = "abc"
val str = "$s.length is ${s.length}"
Output:
abc.length is 3
LANGUAGE IDIOMS & CONCEPTS
STRING TEMPLATES & ENUM CLASSES (II)
▸ Kotlin has a dedicated and expressive
enum class
▸ Can be used very nicely in conjunction
with String templates
enum class Locale(val hello: String) {
DE_DE("Hallo"),
EN_NZ("Hello"),
MI_NZ("Kia Ora")
}
class Customer(val firstName:String,
val lastName:String,
val locale: Locale = Locale.DE_DE) {
fun sayHello() = println(
"${locale.hello}, $firstName $lastName")
}
fun main(args : Array<String>) {
val myCustomer = Customer("Sandra",
"Musterfrau",
Locale.MI_NZ)
myCustomer.sayHello()
}
LANGUAGE IDIOMS & CONCEPTS
NULL SAFETY
▸ Motivation: A better way to deal with NPEs
▸ Kotlin differentiates nullable types from non-
nullable types by adding a ? to the type:
▸ String: no nullable
▸ String?: nullable
▸ Handle manually
▸ Use Safe Call operator ?.
▸ Use the !! operator to allow/trigger a NPE
// Won't compile
var lastName: String = null
// Will compile
var lastNameNullable: String? = null
// Will also not compile
println(lastNameNullable.length)
// Option 1 (-1)
println(if (lastNameNullable != null)
lastNameNullable.length else -1)
// Option 2 (null)
println(lastNameNullable?.length)
// Option 3 (NPE)
println(lastNameNullable!!.length)
LANGUAGE IDIOMS & CONCEPTS
PROPERTIES AND FIELDS
▸ Kotlin classes have mutable or
immutable properties
▸ Default getter/setters for properties,
can be customised
▸ An automated backing field can be
provided by the compiler (if required)
▸ Alternative: use an explicit backing
property
var counter = 0
set(value) {
if (value >= 0)
field = value
}
public class Address {
public var name: String = ...
public var street: String = ...
public var city: String = ...
public var state: String? = ...
public var zip: String = ...
}
LANGUAGE IDIOMS & CONCEPTS
TYPE INFERENCE AND CASTS (I)
▸ When possible, Kotlin will infer the type
of variables
▸ Explicit conversions, type widening and
inference
▸ Smaller types are not subtypes of
bigger types, no implicit conversion
▸ Types are often inferred from the
context
val b: Byte = 1
// This won't work
val i: Int = b
// This will
val i: Int = b.toInt()
val l: Long = 1L + 3
LANGUAGE IDIOMS & CONCEPTS
TYPE INFERENCE AND CASTS (II)
▸ is or !is checks if an object adheres to a
certain type
▸ Smart cast: Compiler tracks is-expressions
for immutable values
▸ works for val local variables and private,
internal or in-module performed casts
▸ works for var local variables if the
variable hasn’t been modified between
check and usage, never for var
properties
fun whatIs(x: Any) {
when (x) {
is Int -> println(x + 42)
is String -> println(x.length)
is IntArray -> println(x.sum())
}
}
whatIs(4) // 46
whatIs("4") // 1
whatIs(intArrayOf(1,2,3,4,5)) // 15
LANGUAGE IDIOMS & CONCEPTS
DATA CLASSES
▸ The POJOs/Beans of other languages
▸ Data classes implicitly create:
▸ getters/setters (non-data classes
have those too) - recommend to use
val as often as possible.
▸ useful implementations for equals(),
hashCode(), toString(), copy()
▸ copy() has default parameters and
can be used to alter a copy
data class ChromeEncryptedPayload(
val encryptedPayload: String,
val encryptionHeader: String,
val cryptoKeyHeader: String)
val pl = ChromeEncryptedPayload(
encryptedPayload = "...",
encryptionHeader = "...",
cryptoKeyHeader = "...")
val anotherPl = pl.copy(
encryptedPayload = "...")
LANGUAGE IDIOMS & CONCEPTS
EXTENSION FUNCTIONS
▸ Allow adding new functionality to a
class without inheritance or Decorators
▸ Kotlin has extension functions as well
as extension properties
▸ Resolved statically, don’t actually
modify the class (excellent example
why this has to be the case at http://
goo.gl/EN6bTs
fun Int.sum(otherInt: Int): Int =
this + otherInt
3.sum(7)
fun Activity.toast(message: CharSequence,
duration: Int =
TOAST.LENGTH_SHORT) {
Toast.makeText(this, message,
duration).show()
}
// In onCreate of an Activity
override fun onCreate(...) {
...
toast("Hi there")
...
}
LANGUAGE IDIOMS & CONCEPTS
LAMBDAS
▸ Anonymous function or “function
literal”, closely related to the ideas of
Higher-Order-Functions
val sum = { x: Int, y: Int -> x + y }
val sum: (Int, Int) -> Int = { x, y ->
x + y }
private fun convertPetListToDomain(list: List<Pet>): List<PetDomain> {
return list.map { convertPetItemToDomain(it) }
}
private fun convertPetItemToDomain(pet: Pet): PetDomain {
return PetDomain(pet.age,pet.size,pet.id,pet.name,pet.sex,pet.breed)
}
LANGUAGE IDIOMS & CONCEPTS
TYPE-SAFE BUILDERS (I)
▸ Builders are a very popular approach in
Groovy to define data in a declarative
way
▸ Often used for:
▸ generating XML or JSON
▸ UI layout (Swing components) etc
▸ In Kotlin, builders even can be type-
checked
JsonBuilder builder = new JsonBuilder()
builder.records {
car {
name 'HSV Maloo'
make 'Holden'
year 2006
country 'Australia'
}
}
String json = JsonOutput.prettyPrint
(builder.toString())
LANGUAGE IDIOMS & CONCEPTS
TYPE-SAFE BUILDERS (II)
▸ html() is a function with a lambda as an
argument (init)
▸ init’s type is a function type with
receiver, this allows you to:
▸ pass receiver (of type HTML) to
function
▸ call members of instance inside the
function
fun result(args: Array<String>) =
html {
head {
title {”HTML in Kotlin"}
}
body {
...
}
}
fun html(init: HTML.() -> Unit): HTML {
val html = HTML()
html.init()
return html
}
LANGUAGE IDIOMS & CONCEPTS
TYPE-SAFE BUILDERS (III)
▸ HTML class has functions to build the
head and the body elements of the
DSL.
▸ Not shown: classes further down in the
hierarchy:
▸ Head, Body etc.
▸ Complete HTML builder example at:
http://goo.gl/TndcC9
class HTML {
...
fun head(headBuilder: Head.() -> Unit) {
head = Head()
head?.headBuilder()
}
fun body(bodyBuilder: Body.() -> Unit) {
body = Body()
body?.bodyBuilder()
}
}
LANGUAGE IDIOMS & CONCEPTS
JAVA-KOTLIN-INTEROP
▸ Java and Kotlin are fully interoperable from an integration point of view
▸ Your Java code can call and use Kotlin code
▸ Your Kotlin code can call and use Java code
▸ The latter is in particular useful because it means you can continue to use pretty
much any existing Android/Java library
▸ Check out Hendrik Kokocinski’s sample Kotlin app that uses all kinds of well
known Android/Java libs: https://goo.gl/xdYqf5
LANGUAGE IDIOMS & CONCEPTS
OVERVIEW
▸ Immutability
▸ String templates & Enum classes
▸ Null safety
▸ Properties and Fields
▸ Type inference and casts
▸ Data classes
▸ Syntactic sugar (loops, ranges etc)
▸ Extension functions
▸ Lambdas
▸ Collection API
▸ Type-safe builders
▸ Java-Kotlin-Interop
KOTLIN AND ANDROID
https://realm.io/assets/img/news/tutorial-kotlin-anko-cover.png
APP
STEP 1 - KOTLIN SETUP
▸ Setup Kotlin Plugin and tooling
▸ Automated vs. manual
APP
STEP 2 - REFACTOR JAVA -> KOTLIN
▸ Kotlin Source Path
APP
STEP 3 - KOTLIN ANDROID EXTENSIONS
▸ Finding views with KAE (built into the plugin)
APP
STEP 4 - MORE KAE
▸ KAE Click handler - compare to classic Kotlin code
▸ Lambdas
APP
STEP 5 - BUTTERKNIFE
▸ View Bindings with Butterknife in Kotlin
▸ KAPT setup
APP
STEP 6 - RECYCLERVIEW AND SOME DATA
▸ Adding Adapter and RecyclerView
▸ Displaying hardcoded data for now
APP
STEP 7 - DATA (I)
▸ Loading and returning some hard JSON sample data
▸ Companion object
▸ No UI changes, use debugger in MainActivity
APP
STEP 8 - DATA (II) / GSON PARSING
▸ Kotlin data classes
▸ GSON parsing
▸ String templates
▸ No UI changes, use debugger in MainActivity
APP
STEP 9 - ARCHITECTURE
▸ Command pattern
▸ Introducing Anko for async
▸ More String templates
▸ with
▸ Interface
▸ .map
ANKO DSL
ANKO DSL
WHAT IS A DSL?
▸ Domain-Specific Language
▸ Limited expressiveness:
▸ DSLs are usually not general-purpose languages
▸ strongly focussed on a particular domain
▸ examples: SQL, Ant XML, XSLT, Gradle etc.
ANKO DSL
A DSL FOR LAYOUTS
▸ The most important element of Anko is the Layout DSL
▸ Idea: replace XML layout definitions by Kotlin code - without having to build
the layout in a fully programmatic sense
▸ Modular: as we’re talking about UI/Layout, it’s very important to select the
right library for your minSDKVersion
▸ Extensible: you can add your own DSL elements for custom UI controls
ANKO DSL
LAYOUT XML
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<EditText
android:layout_width="match_parent"
android:gravity="center"
android:text="@string/empty_todos_message"
android:layout_weight="7"
android:layout_height="wrap_content" />
<Button
android:layout_width="match_parent"
android:layout_weight="1"
android:text="Say Hello"
android:layout_height="0dp" />
</LinearLayout>
ANKO DSL
PROGRAMMATIC LAYOUT IN KOTLIN
val act = this
val layout = LinearLayout(act)
layout.orientation = LinearLayout.VERTICAL
val name = EditText(act)
val button = Button(act)
button.text = "Say Hello"
button.setOnClickListener {
Toast.makeText(act, "Hello, ${name.text}!", Toast.LENGTH_SHORT).show()
}
layout.addView(name)
layout.addView(button)
ANKO DSL
ANKO DSL
verticalLayout {
val name = editText()
button("Say Hello") {
onClick { toast("Hello, ${name.text}!") }
}
}
ANKO DSL
ANKO DSL INTERNALS
▸ Anko DSL example from previous slide looks very similar to the earlier HTML
builder example
▸ Anko uses extension functions arranged into type-safe builders and lambdas
▸ You don’t have to write all those extensions by hand though - Anko generates
them based on the Android SDK’s android.jar
ANKO DSL
GETTING STARTED WITH ANKO DSL (I)
▸ Depending on minSdkVersion of project, import:

compile "org.jetbrains.anko:anko-sdk{15|19|21|23}:0.9"
▸ If the project uses an Android Support library, import matching Anko library:

compile "org.jetbrains.anko:anko-recyclerview-v7:0.9"
ANKO DSL
GETTING STARTED WITH ANKO DSL (II)
▸ General approach:
▸ Anko DSL automatically becomes
available in onCreate() in an Activity
▸ no need for setContentView(), Anko
DSL also automatically sets the
content view for activities
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
verticalLayout {
padding = dip(30)
editText {
hint = "Name"
textSize = 24f
}
editText {
hint = "Password"
textSize = 24f
}
button("Login") {
textSize = 26f
}
}
}
ANKO DSL
ANKO DSL IN FRAGMENTS
▸ In fragments, use 

onCreateView(…)
▸ Returns UI {…}.view:
▸ mandatory before Anko 0.8
▸ works well for Fragments
▸ createTodo() is a fragment-private
method
override fun onCreateView(inflater: LayoutInflater?,
container: ViewGroup?,
savedInstanceState: Bundle?): View? {
return UI {
verticalLayout {
padding = dip(24)
var title = editText {
id = R.id.title
hintResource = R.string.hint
}
...
button {
id = R.id.add
textResource = R.string.add
onClick { view -> createTodo(title, desc) }
}
}
}.view
}
ANKO DSL
ANKO COMPONENTS (I)
▸ Often it’s nicer to have UI code separated from onCreate or other livecycle
methods
▸ AnkoComponent helps organising your UI code in their own classes
ANKO DSL
ANKO COMPONENTS (II)
override fun onCreateView(...)= EditFragmentUI().createView(AnkoContext.create(ctx,this))
class EditFragmentUI : AnkoComponent<EditFragment> {
override fun createView(ui: AnkoContext<EditFragment>) = with(ui) {
verticalLayout {
padding = dip(24)
var title = editText {
id = R.id.title
hintResource = R.string.hint
}
...
button {
id = R.id.add
textResource = R.string.add
onClick { view -> ui.owner.createTodoFrom(title, desc) }
}
}
}
}
ANKO DSL
ANKO COMPONENTS (III)
▸ Anko Preview plugin for
AnkoComponent layouts
▸ Get it here: http://goo.gl/5CVmAA
▸ Can preview layouts and convert XML
to Anko DSL
▸ Can be fiddly to get going with AS,
Kotlin plugin versions
ANKO DSL
EXTENDING ANKOS DSL FUNCTIONALITY (I)
▸ Multiple ways to do this:
▸ insert an existing XML layout into an Anko DSL declaration:

▸ adding new DSL elements to the language
include<View>(R.layout.mylayout) { ... }
inline fun ViewManager.customView(theme: Int = 0) = customView(theme) {}
inline fun ViewManager.customView(theme: Int = 0, init: CustomView.() -> Unit) =
ankoView({ CustomView(it) }, theme, init)
inline fun Activity.customView(theme: Int = 0) = customView(theme) {}
inline fun Activity.customView(theme: Int = 0, init: CustomView.() -> Unit) =
ankoView({ CustomView(it) }, theme, init)
ANKO DSL
EXTENDING ANKOS DSL FUNCTIONALITY (II)
▸ Extending Anko’s DSL to support your own custom view groups is currently rather
painful
▸ Essentially it comes down to .lparams (for layout purposes) not being easily accessible
▸ More here:
▸ http://goo.gl/qpb3SL
▸ http://goo.gl/tMHs2c
▸ Fix targeted for Anko 0.9.1
THE HIDDEN PARTS OF
ANKO
THE HIDDEN PARTS OF ANKO
BUT THERE’S MORE
▸ Intent wrappers for various purposes: e.g. sendSMS(number, [text])
▸ Intent builders
▸ Service shortcuts
▸ Configuration qualifiers: configuration(screenSize = ScreenSize.LARGE,
orientation = Orientation.LANDSCAPE) { … }
▸ Asynchronous tasks
▸ SQLLite
THE HIDDEN PARTS OF ANKO
INTENT WRAPPERS AND SERVICE SHORTCUTS
▸ Anko provides wrappers for commonly used Intents:
▸ makeCall(number), sendSMS(number, text), browse(url) etc.
▸ Shortcuts to Android services:
▸ notificationManager, displayManager, sensorManager etc.
▸ Useful, but both not major features of Anko
THE HIDDEN PARTS OF ANKO
INTENT BUILDERS
▸ Syntactic sugar to cut down the amount of code needed to start a new activity
val intent = Intent(this, javaClass<MyActivity>())
intent.putExtra("customerId", 4711)
intent.putExtra("country", "NZ")
startActivity(intent)
startActivity(Intent(this, MyActivity::class.java).
putExtra("customerId", 4711).putExtra("country", "NZ"))
startActivity<MyActivity>("customerId" to 4711, "country" to "NZ")
THE HIDDEN PARTS OF ANKO
CONFIGURATION QUALIFIERS
▸ “CSS Media Queries for Android”
▸ Screen features:
▸ screenSize, density, orientation, long, 

nightMode, rightToLeft, smallestWidth
▸ SDK versions:
▸ fromSdk, sdk
▸ Other:
▸ language, uiMode
configuration(screenSize = ScreenSize.LARGE,
orientation =
Orientation.LANDSCAPE)
{
/*
This code will be only executed
if the screen is large and its
orientation is landscape
*/
}
THE HIDDEN PARTS OF ANKO
ASYNC DSL
▸ Does anyone enjoy working with AsyncTasks?
▸ Anko: async and asyncResult (return future respectively future with result)
async() {
val result = PetFindCommand("90210","cat").execute()
uiThread {
animalList.adapter = AnimalListAdapter(result,
object: AnimalListAdapter.ItemClickListener{
override fun invoke(pet:Pet) {
toast(pet.name)
}
}
)
}
}
THE HIDDEN PARTS OF ANKO
SQLITE (I)
▸ Working with SQLite usually requires a lot of boilerplate code and try/catch-
structures, issues around concurrency, dealing with cached code and
references etc.
▸ Anko aims to make that easier
▸ Dependency: compile ‘org.jetbrains.anko:anko-sqlite:0.9'
▸ Setup class extending ManagedSQLiteOpenHelper in your code
THE HIDDEN PARTS OF ANKO
SQLITE (II)
▸ database.use ensures DB is opened
and closed correctly
▸ Asynchronous use of the DB is possible
through Anko’s async DSL
▸ Important: There can still be
SQLiteExceptions when handling SQL
code - Anko doesn’t abstract those.
▸ Handling of cursors and parsing data
via lambdas
database.use {
createTable("Customer", ifNotExists = true,
"id" to INTEGER + PRIMARY_KEY + UNIQUE,
"name" to TEXT,
"photo" to BLOB)
}
APP
STEP 10 - CLICK ON LIST
▸ Adapter/RecyclerView click handler changes
▸ when-statement
APP
STEP 11 - EXCEPTIONS
▸ Exception handler in Anko
APP
STEP 12 - ANKO DSL
▸ Anko layout for main view
▸ Removing layout XML and replacing it with Anko DSL
APP
STEP 13 - ANKO COMPONENTS
▸ Refactoring into Anko component
APP
STEP 14
▸ Mini refactoring for better testing
▸ jUnit tests in Kotlin
APP
STEP 15
▸ Using Spek for BDD testing
APP
IDEAS
▸ Add second Activity or Fragment to display and edit details
▸ Change layout to ConstraintLayout
▸ Use Kotson instead of Gson
▸ Store data locally
▸ Change RecyclerView to Anko Layout DSL
▸ Use Butterknife instead of Kotterknife
▸ Write some proper tests
▸ Try Android integration tests
MORE
GDG WELLINTON
MORE
WELLINGTON.KT
RESOURCES
RESOURCES
▸ Kotlin: http://kotlinlang.org
▸ Anko: https://github.com/Kotlin/anko
▸ Kotter Knife: https://github.com/JakeWharton/kotterknife
▸ Spek: http://jetbrains.github.io/spek/
▸ Kotson: https://github.com/SalomonBrys/Kotson
RESOURCES
GET IN TOUCH
Kai Koenig
Email: kai@ventego-creative.co.nz
Twitter: @AgentK
Kate Henderson
Email: hi@kate.nz
Twitter: @Mistyepd

More Related Content

What's hot

Taking Kotlin to production, Seriously
Taking Kotlin to production, SeriouslyTaking Kotlin to production, Seriously
Taking Kotlin to production, Seriously
Haim Yadid
 
Fall in love with Kotlin
Fall in love with KotlinFall in love with Kotlin
Fall in love with Kotlin
Hari Vignesh Jayapalan
 
Kotlin hands on - MorningTech ekito 2017
Kotlin hands on - MorningTech ekito 2017Kotlin hands on - MorningTech ekito 2017
Kotlin hands on - MorningTech ekito 2017
Arnaud Giuliani
 
Introduction to kotlin
Introduction to kotlinIntroduction to kotlin
Introduction to kotlin
NAVER Engineering
 
Kotlin cheat sheet by ekito
Kotlin cheat sheet by ekitoKotlin cheat sheet by ekito
Kotlin cheat sheet by ekito
Arnaud Giuliani
 
Design patterns with kotlin
Design patterns with kotlinDesign patterns with kotlin
Design patterns with kotlin
Alexey Soshin
 
eMan Dev Meetup: Kotlin - A Language we should know it exists (part 02/03) 18...
eMan Dev Meetup: Kotlin - A Language we should know it exists (part 02/03) 18...eMan Dev Meetup: Kotlin - A Language we should know it exists (part 02/03) 18...
eMan Dev Meetup: Kotlin - A Language we should know it exists (part 02/03) 18...
eMan s.r.o.
 
Large Scale JavaScript with TypeScript
Large Scale JavaScript with TypeScriptLarge Scale JavaScript with TypeScript
Large Scale JavaScript with TypeScriptOliver Zeigermann
 
Groovy Programming Language
Groovy Programming LanguageGroovy Programming Language
Groovy Programming Language
Aniruddha Chakrabarti
 
Beauty & the Beast - Java VS TypeScript
Beauty & the Beast - Java VS TypeScriptBeauty & the Beast - Java VS TypeScript
Beauty & the Beast - Java VS TypeScript
Hendrik Ebbers
 
Kotlin: A pragmatic language by JetBrains
Kotlin: A pragmatic language by JetBrainsKotlin: A pragmatic language by JetBrains
Kotlin: A pragmatic language by JetBrains
Jigar Gosar
 
Kotlin a problem solver - gdd extended pune
Kotlin   a problem solver - gdd extended puneKotlin   a problem solver - gdd extended pune
Kotlin a problem solver - gdd extended pune
Hardik Trivedi
 
eMan Dev Meetup: Kotlin For Android (part 03/03) 18.5.2017
eMan Dev Meetup: Kotlin For Android (part 03/03) 18.5.2017eMan Dev Meetup: Kotlin For Android (part 03/03) 18.5.2017
eMan Dev Meetup: Kotlin For Android (part 03/03) 18.5.2017
eMan s.r.o.
 
Building microservices with Kotlin
Building microservices with KotlinBuilding microservices with Kotlin
Building microservices with Kotlin
Haim Yadid
 
Rapid Development with Ruby/JRuby and Rails
Rapid Development with Ruby/JRuby and RailsRapid Development with Ruby/JRuby and Rails
Rapid Development with Ruby/JRuby and Railselliando dias
 
A quick and fast intro to Kotlin
A quick and fast intro to Kotlin A quick and fast intro to Kotlin
A quick and fast intro to Kotlin
XPeppers
 
C++ concept of Polymorphism
C++ concept of  PolymorphismC++ concept of  Polymorphism
C++ concept of Polymorphism
kiran Patel
 
Kotlin - The Swiss army knife of programming languages - Visma Mobile Meet-up...
Kotlin - The Swiss army knife of programming languages - Visma Mobile Meet-up...Kotlin - The Swiss army knife of programming languages - Visma Mobile Meet-up...
Kotlin - The Swiss army knife of programming languages - Visma Mobile Meet-up...
Tudor Dragan
 

What's hot (20)

Taking Kotlin to production, Seriously
Taking Kotlin to production, SeriouslyTaking Kotlin to production, Seriously
Taking Kotlin to production, Seriously
 
Fall in love with Kotlin
Fall in love with KotlinFall in love with Kotlin
Fall in love with Kotlin
 
Kotlin hands on - MorningTech ekito 2017
Kotlin hands on - MorningTech ekito 2017Kotlin hands on - MorningTech ekito 2017
Kotlin hands on - MorningTech ekito 2017
 
Introduction to kotlin
Introduction to kotlinIntroduction to kotlin
Introduction to kotlin
 
Kotlin cheat sheet by ekito
Kotlin cheat sheet by ekitoKotlin cheat sheet by ekito
Kotlin cheat sheet by ekito
 
Design patterns with kotlin
Design patterns with kotlinDesign patterns with kotlin
Design patterns with kotlin
 
eMan Dev Meetup: Kotlin - A Language we should know it exists (part 02/03) 18...
eMan Dev Meetup: Kotlin - A Language we should know it exists (part 02/03) 18...eMan Dev Meetup: Kotlin - A Language we should know it exists (part 02/03) 18...
eMan Dev Meetup: Kotlin - A Language we should know it exists (part 02/03) 18...
 
Large Scale JavaScript with TypeScript
Large Scale JavaScript with TypeScriptLarge Scale JavaScript with TypeScript
Large Scale JavaScript with TypeScript
 
FTD JVM Internals
FTD JVM InternalsFTD JVM Internals
FTD JVM Internals
 
Groovy Programming Language
Groovy Programming LanguageGroovy Programming Language
Groovy Programming Language
 
Beauty & the Beast - Java VS TypeScript
Beauty & the Beast - Java VS TypeScriptBeauty & the Beast - Java VS TypeScript
Beauty & the Beast - Java VS TypeScript
 
Kotlin: A pragmatic language by JetBrains
Kotlin: A pragmatic language by JetBrainsKotlin: A pragmatic language by JetBrains
Kotlin: A pragmatic language by JetBrains
 
Kotlin a problem solver - gdd extended pune
Kotlin   a problem solver - gdd extended puneKotlin   a problem solver - gdd extended pune
Kotlin a problem solver - gdd extended pune
 
Meta Object Protocols
Meta Object ProtocolsMeta Object Protocols
Meta Object Protocols
 
eMan Dev Meetup: Kotlin For Android (part 03/03) 18.5.2017
eMan Dev Meetup: Kotlin For Android (part 03/03) 18.5.2017eMan Dev Meetup: Kotlin For Android (part 03/03) 18.5.2017
eMan Dev Meetup: Kotlin For Android (part 03/03) 18.5.2017
 
Building microservices with Kotlin
Building microservices with KotlinBuilding microservices with Kotlin
Building microservices with Kotlin
 
Rapid Development with Ruby/JRuby and Rails
Rapid Development with Ruby/JRuby and RailsRapid Development with Ruby/JRuby and Rails
Rapid Development with Ruby/JRuby and Rails
 
A quick and fast intro to Kotlin
A quick and fast intro to Kotlin A quick and fast intro to Kotlin
A quick and fast intro to Kotlin
 
C++ concept of Polymorphism
C++ concept of  PolymorphismC++ concept of  Polymorphism
C++ concept of Polymorphism
 
Kotlin - The Swiss army knife of programming languages - Visma Mobile Meet-up...
Kotlin - The Swiss army knife of programming languages - Visma Mobile Meet-up...Kotlin - The Swiss army knife of programming languages - Visma Mobile Meet-up...
Kotlin - The Swiss army knife of programming languages - Visma Mobile Meet-up...
 

Similar to Android 101 - Building a simple app with Kotlin in 90 minutes

Little Helpers for Android Development with Kotlin
Little Helpers for Android Development with KotlinLittle Helpers for Android Development with Kotlin
Little Helpers for Android Development with Kotlin
Kai Koenig
 
Anko - The Ultimate Ninja of Kotlin Libraries?
Anko - The Ultimate Ninja of Kotlin Libraries?Anko - The Ultimate Ninja of Kotlin Libraries?
Anko - The Ultimate Ninja of Kotlin Libraries?
Kai Koenig
 
Kotlin coroutines and spring framework
Kotlin coroutines and spring frameworkKotlin coroutines and spring framework
Kotlin coroutines and spring framework
Sunghyouk Bae
 
Why Kotlin is your next language?
Why Kotlin is your next language? Why Kotlin is your next language?
Why Kotlin is your next language?
Aliaksei Zhynhiarouski
 
Android 101 - Kotlin ( Future of Android Development)
Android 101 - Kotlin ( Future of Android Development)Android 101 - Kotlin ( Future of Android Development)
Android 101 - Kotlin ( Future of Android Development)
Hassan Abid
 
Kotlin fundamentals - By: Ipan Ardian
Kotlin fundamentals - By: Ipan ArdianKotlin fundamentals - By: Ipan Ardian
Kotlin fundamentals - By: Ipan Ardian
Rizal Khilman
 
Kotlin Fundamentals
Kotlin Fundamentals Kotlin Fundamentals
Kotlin Fundamentals
Ipan Ardian
 
KotlinForJavaDevelopers-UJUG.pptx
KotlinForJavaDevelopers-UJUG.pptxKotlinForJavaDevelopers-UJUG.pptx
KotlinForJavaDevelopers-UJUG.pptx
Ian Robertson
 
Having Fun with Kotlin Android - DILo Surabaya
Having Fun with Kotlin Android - DILo SurabayaHaving Fun with Kotlin Android - DILo Surabaya
Having Fun with Kotlin Android - DILo Surabaya
DILo Surabaya
 
What’s new in Kotlin?
What’s new in Kotlin?What’s new in Kotlin?
What’s new in Kotlin?
Squareboat
 
Koin Quickstart
Koin QuickstartKoin Quickstart
Koin Quickstart
Matthew Clarke
 
Introduction to Kotlin
Introduction to KotlinIntroduction to Kotlin
Introduction to Kotlin
Patrick Yin
 
Writing Kotlin Multiplatform libraries that your iOS teammates are gonna love
Writing Kotlin Multiplatform libraries that your iOS teammates are gonna loveWriting Kotlin Multiplatform libraries that your iOS teammates are gonna love
Writing Kotlin Multiplatform libraries that your iOS teammates are gonna love
André Oriani
 
Being Expressive in Code
Being Expressive in CodeBeing Expressive in Code
Being Expressive in Code
Eamonn Boyle
 
Poniendo Kotlin en producción a palos (Kotlin in production, the hard way)
Poniendo Kotlin en producción a palos (Kotlin in production, the hard way)Poniendo Kotlin en producción a palos (Kotlin in production, the hard way)
Poniendo Kotlin en producción a palos (Kotlin in production, the hard way)
Andrés Viedma Peláez
 
Kotlin / Android Update
Kotlin / Android UpdateKotlin / Android Update
Kotlin / Android Update
Garth Gilmour
 
Kotlin for Android devs
Kotlin for Android devsKotlin for Android devs
Kotlin for Android devs
Adit Lal
 
Design patterns with kotlin
Design patterns with kotlinDesign patterns with kotlin
Design patterns with kotlin
Alexey Soshin
 
Kotlin Coroutines and Android sitting in a tree
Kotlin Coroutines and Android sitting in a treeKotlin Coroutines and Android sitting in a tree
Kotlin Coroutines and Android sitting in a tree
Kai Koenig
 
Clean Code 2
Clean Code 2Clean Code 2
Clean Code 2
Fredrik Wendt
 

Similar to Android 101 - Building a simple app with Kotlin in 90 minutes (20)

Little Helpers for Android Development with Kotlin
Little Helpers for Android Development with KotlinLittle Helpers for Android Development with Kotlin
Little Helpers for Android Development with Kotlin
 
Anko - The Ultimate Ninja of Kotlin Libraries?
Anko - The Ultimate Ninja of Kotlin Libraries?Anko - The Ultimate Ninja of Kotlin Libraries?
Anko - The Ultimate Ninja of Kotlin Libraries?
 
Kotlin coroutines and spring framework
Kotlin coroutines and spring frameworkKotlin coroutines and spring framework
Kotlin coroutines and spring framework
 
Why Kotlin is your next language?
Why Kotlin is your next language? Why Kotlin is your next language?
Why Kotlin is your next language?
 
Android 101 - Kotlin ( Future of Android Development)
Android 101 - Kotlin ( Future of Android Development)Android 101 - Kotlin ( Future of Android Development)
Android 101 - Kotlin ( Future of Android Development)
 
Kotlin fundamentals - By: Ipan Ardian
Kotlin fundamentals - By: Ipan ArdianKotlin fundamentals - By: Ipan Ardian
Kotlin fundamentals - By: Ipan Ardian
 
Kotlin Fundamentals
Kotlin Fundamentals Kotlin Fundamentals
Kotlin Fundamentals
 
KotlinForJavaDevelopers-UJUG.pptx
KotlinForJavaDevelopers-UJUG.pptxKotlinForJavaDevelopers-UJUG.pptx
KotlinForJavaDevelopers-UJUG.pptx
 
Having Fun with Kotlin Android - DILo Surabaya
Having Fun with Kotlin Android - DILo SurabayaHaving Fun with Kotlin Android - DILo Surabaya
Having Fun with Kotlin Android - DILo Surabaya
 
What’s new in Kotlin?
What’s new in Kotlin?What’s new in Kotlin?
What’s new in Kotlin?
 
Koin Quickstart
Koin QuickstartKoin Quickstart
Koin Quickstart
 
Introduction to Kotlin
Introduction to KotlinIntroduction to Kotlin
Introduction to Kotlin
 
Writing Kotlin Multiplatform libraries that your iOS teammates are gonna love
Writing Kotlin Multiplatform libraries that your iOS teammates are gonna loveWriting Kotlin Multiplatform libraries that your iOS teammates are gonna love
Writing Kotlin Multiplatform libraries that your iOS teammates are gonna love
 
Being Expressive in Code
Being Expressive in CodeBeing Expressive in Code
Being Expressive in Code
 
Poniendo Kotlin en producción a palos (Kotlin in production, the hard way)
Poniendo Kotlin en producción a palos (Kotlin in production, the hard way)Poniendo Kotlin en producción a palos (Kotlin in production, the hard way)
Poniendo Kotlin en producción a palos (Kotlin in production, the hard way)
 
Kotlin / Android Update
Kotlin / Android UpdateKotlin / Android Update
Kotlin / Android Update
 
Kotlin for Android devs
Kotlin for Android devsKotlin for Android devs
Kotlin for Android devs
 
Design patterns with kotlin
Design patterns with kotlinDesign patterns with kotlin
Design patterns with kotlin
 
Kotlin Coroutines and Android sitting in a tree
Kotlin Coroutines and Android sitting in a treeKotlin Coroutines and Android sitting in a tree
Kotlin Coroutines and Android sitting in a tree
 
Clean Code 2
Clean Code 2Clean Code 2
Clean Code 2
 

More from Kai Koenig

Why a whole country skipped a day - Fun with Timezones
Why a whole country skipped a day - Fun with Timezones Why a whole country skipped a day - Fun with Timezones
Why a whole country skipped a day - Fun with Timezones
Kai Koenig
 
Android 103 - Firebase and Architecture Components
Android 103 - Firebase and Architecture ComponentsAndroid 103 - Firebase and Architecture Components
Android 103 - Firebase and Architecture Components
Kai Koenig
 
Android 102 - Flow, Layouts and other things
Android 102 - Flow, Layouts and other thingsAndroid 102 - Flow, Layouts and other things
Android 102 - Flow, Layouts and other things
Kai Koenig
 
Kotlin Coroutines and Android sitting in a tree - 2018 version
Kotlin Coroutines and Android sitting in a tree - 2018 versionKotlin Coroutines and Android sitting in a tree - 2018 version
Kotlin Coroutines and Android sitting in a tree - 2018 version
Kai Koenig
 
Improving your CFML code quality
Improving your CFML code qualityImproving your CFML code quality
Improving your CFML code quality
Kai Koenig
 
API management with Taffy and API Blueprint
API management with Taffy and API BlueprintAPI management with Taffy and API Blueprint
API management with Taffy and API Blueprint
Kai Koenig
 
Introduction to Data Mining
Introduction to Data MiningIntroduction to Data Mining
Introduction to Data Mining
Kai Koenig
 
Garbage First and you
Garbage First and youGarbage First and you
Garbage First and you
Kai Koenig
 
Real World Lessons in jQuery Mobile
Real World Lessons in jQuery MobileReal World Lessons in jQuery Mobile
Real World Lessons in jQuery Mobile
Kai Koenig
 
The JVM is your friend
The JVM is your friendThe JVM is your friend
The JVM is your friend
Kai Koenig
 
Regular Expressions 101
Regular Expressions 101Regular Expressions 101
Regular Expressions 101
Kai Koenig
 
There's a time and a place
There's a time and a placeThere's a time and a place
There's a time and a place
Kai Koenig
 
Clojure - an introduction (and some CFML)
Clojure - an introduction (and some CFML)Clojure - an introduction (and some CFML)
Clojure - an introduction (and some CFML)
Kai Koenig
 
AngularJS for designers and developers
AngularJS for designers and developersAngularJS for designers and developers
AngularJS for designers and developersKai Koenig
 
Cryptography for developers
Cryptography for developersCryptography for developers
Cryptography for developers
Kai Koenig
 
JVM and Garbage Collection Tuning
JVM and Garbage Collection TuningJVM and Garbage Collection Tuning
JVM and Garbage Collection TuningKai Koenig
 
Apps vs. Sites vs. Content - a vendor-agnostic view on building stuff for the...
Apps vs. Sites vs. Content - a vendor-agnostic view on building stuff for the...Apps vs. Sites vs. Content - a vendor-agnostic view on building stuff for the...
Apps vs. Sites vs. Content - a vendor-agnostic view on building stuff for the...
Kai Koenig
 

More from Kai Koenig (17)

Why a whole country skipped a day - Fun with Timezones
Why a whole country skipped a day - Fun with Timezones Why a whole country skipped a day - Fun with Timezones
Why a whole country skipped a day - Fun with Timezones
 
Android 103 - Firebase and Architecture Components
Android 103 - Firebase and Architecture ComponentsAndroid 103 - Firebase and Architecture Components
Android 103 - Firebase and Architecture Components
 
Android 102 - Flow, Layouts and other things
Android 102 - Flow, Layouts and other thingsAndroid 102 - Flow, Layouts and other things
Android 102 - Flow, Layouts and other things
 
Kotlin Coroutines and Android sitting in a tree - 2018 version
Kotlin Coroutines and Android sitting in a tree - 2018 versionKotlin Coroutines and Android sitting in a tree - 2018 version
Kotlin Coroutines and Android sitting in a tree - 2018 version
 
Improving your CFML code quality
Improving your CFML code qualityImproving your CFML code quality
Improving your CFML code quality
 
API management with Taffy and API Blueprint
API management with Taffy and API BlueprintAPI management with Taffy and API Blueprint
API management with Taffy and API Blueprint
 
Introduction to Data Mining
Introduction to Data MiningIntroduction to Data Mining
Introduction to Data Mining
 
Garbage First and you
Garbage First and youGarbage First and you
Garbage First and you
 
Real World Lessons in jQuery Mobile
Real World Lessons in jQuery MobileReal World Lessons in jQuery Mobile
Real World Lessons in jQuery Mobile
 
The JVM is your friend
The JVM is your friendThe JVM is your friend
The JVM is your friend
 
Regular Expressions 101
Regular Expressions 101Regular Expressions 101
Regular Expressions 101
 
There's a time and a place
There's a time and a placeThere's a time and a place
There's a time and a place
 
Clojure - an introduction (and some CFML)
Clojure - an introduction (and some CFML)Clojure - an introduction (and some CFML)
Clojure - an introduction (and some CFML)
 
AngularJS for designers and developers
AngularJS for designers and developersAngularJS for designers and developers
AngularJS for designers and developers
 
Cryptography for developers
Cryptography for developersCryptography for developers
Cryptography for developers
 
JVM and Garbage Collection Tuning
JVM and Garbage Collection TuningJVM and Garbage Collection Tuning
JVM and Garbage Collection Tuning
 
Apps vs. Sites vs. Content - a vendor-agnostic view on building stuff for the...
Apps vs. Sites vs. Content - a vendor-agnostic view on building stuff for the...Apps vs. Sites vs. Content - a vendor-agnostic view on building stuff for the...
Apps vs. Sites vs. Content - a vendor-agnostic view on building stuff for the...
 

Recently uploaded

GraphSummit Paris - The art of the possible with Graph Technology
GraphSummit Paris - The art of the possible with Graph TechnologyGraphSummit Paris - The art of the possible with Graph Technology
GraphSummit Paris - The art of the possible with Graph Technology
Neo4j
 
Quarkus Hidden and Forbidden Extensions
Quarkus Hidden and Forbidden ExtensionsQuarkus Hidden and Forbidden Extensions
Quarkus Hidden and Forbidden Extensions
Max Andersen
 
Pro Unity Game Development with C-sharp Book
Pro Unity Game Development with C-sharp BookPro Unity Game Development with C-sharp Book
Pro Unity Game Development with C-sharp Book
abdulrafaychaudhry
 
Lecture 1 Introduction to games development
Lecture 1 Introduction to games developmentLecture 1 Introduction to games development
Lecture 1 Introduction to games development
abdulrafaychaudhry
 
May Marketo Masterclass, London MUG May 22 2024.pdf
May Marketo Masterclass, London MUG May 22 2024.pdfMay Marketo Masterclass, London MUG May 22 2024.pdf
May Marketo Masterclass, London MUG May 22 2024.pdf
Adele Miller
 
Globus Compute wth IRI Workflows - GlobusWorld 2024
Globus Compute wth IRI Workflows - GlobusWorld 2024Globus Compute wth IRI Workflows - GlobusWorld 2024
Globus Compute wth IRI Workflows - GlobusWorld 2024
Globus
 
Exploring Innovations in Data Repository Solutions - Insights from the U.S. G...
Exploring Innovations in Data Repository Solutions - Insights from the U.S. G...Exploring Innovations in Data Repository Solutions - Insights from the U.S. G...
Exploring Innovations in Data Repository Solutions - Insights from the U.S. G...
Globus
 
Navigating the Metaverse: A Journey into Virtual Evolution"
Navigating the Metaverse: A Journey into Virtual Evolution"Navigating the Metaverse: A Journey into Virtual Evolution"
Navigating the Metaverse: A Journey into Virtual Evolution"
Donna Lenk
 
How Recreation Management Software Can Streamline Your Operations.pptx
How Recreation Management Software Can Streamline Your Operations.pptxHow Recreation Management Software Can Streamline Your Operations.pptx
How Recreation Management Software Can Streamline Your Operations.pptx
wottaspaceseo
 
Automated software refactoring with OpenRewrite and Generative AI.pptx.pdf
Automated software refactoring with OpenRewrite and Generative AI.pptx.pdfAutomated software refactoring with OpenRewrite and Generative AI.pptx.pdf
Automated software refactoring with OpenRewrite and Generative AI.pptx.pdf
timtebeek1
 
Providing Globus Services to Users of JASMIN for Environmental Data Analysis
Providing Globus Services to Users of JASMIN for Environmental Data AnalysisProviding Globus Services to Users of JASMIN for Environmental Data Analysis
Providing Globus Services to Users of JASMIN for Environmental Data Analysis
Globus
 
In 2015, I used to write extensions for Joomla, WordPress, phpBB3, etc and I ...
In 2015, I used to write extensions for Joomla, WordPress, phpBB3, etc and I ...In 2015, I used to write extensions for Joomla, WordPress, phpBB3, etc and I ...
In 2015, I used to write extensions for Joomla, WordPress, phpBB3, etc and I ...
Juraj Vysvader
 
Innovating Inference - Remote Triggering of Large Language Models on HPC Clus...
Innovating Inference - Remote Triggering of Large Language Models on HPC Clus...Innovating Inference - Remote Triggering of Large Language Models on HPC Clus...
Innovating Inference - Remote Triggering of Large Language Models on HPC Clus...
Globus
 
Text-Summarization-of-Breaking-News-Using-Fine-tuning-BART-Model.pptx
Text-Summarization-of-Breaking-News-Using-Fine-tuning-BART-Model.pptxText-Summarization-of-Breaking-News-Using-Fine-tuning-BART-Model.pptx
Text-Summarization-of-Breaking-News-Using-Fine-tuning-BART-Model.pptx
ShamsuddeenMuhammadA
 
BoxLang: Review our Visionary Licenses of 2024
BoxLang: Review our Visionary Licenses of 2024BoxLang: Review our Visionary Licenses of 2024
BoxLang: Review our Visionary Licenses of 2024
Ortus Solutions, Corp
 
Graspan: A Big Data System for Big Code Analysis
Graspan: A Big Data System for Big Code AnalysisGraspan: A Big Data System for Big Code Analysis
Graspan: A Big Data System for Big Code Analysis
Aftab Hussain
 
Vitthal Shirke Java Microservices Resume.pdf
Vitthal Shirke Java Microservices Resume.pdfVitthal Shirke Java Microservices Resume.pdf
Vitthal Shirke Java Microservices Resume.pdf
Vitthal Shirke
 
A Study of Variable-Role-based Feature Enrichment in Neural Models of Code
A Study of Variable-Role-based Feature Enrichment in Neural Models of CodeA Study of Variable-Role-based Feature Enrichment in Neural Models of Code
A Study of Variable-Role-based Feature Enrichment in Neural Models of Code
Aftab Hussain
 
Top 7 Unique WhatsApp API Benefits | Saudi Arabia
Top 7 Unique WhatsApp API Benefits | Saudi ArabiaTop 7 Unique WhatsApp API Benefits | Saudi Arabia
Top 7 Unique WhatsApp API Benefits | Saudi Arabia
Yara Milbes
 
openEuler Case Study - The Journey to Supply Chain Security
openEuler Case Study - The Journey to Supply Chain SecurityopenEuler Case Study - The Journey to Supply Chain Security
openEuler Case Study - The Journey to Supply Chain Security
Shane Coughlan
 

Recently uploaded (20)

GraphSummit Paris - The art of the possible with Graph Technology
GraphSummit Paris - The art of the possible with Graph TechnologyGraphSummit Paris - The art of the possible with Graph Technology
GraphSummit Paris - The art of the possible with Graph Technology
 
Quarkus Hidden and Forbidden Extensions
Quarkus Hidden and Forbidden ExtensionsQuarkus Hidden and Forbidden Extensions
Quarkus Hidden and Forbidden Extensions
 
Pro Unity Game Development with C-sharp Book
Pro Unity Game Development with C-sharp BookPro Unity Game Development with C-sharp Book
Pro Unity Game Development with C-sharp Book
 
Lecture 1 Introduction to games development
Lecture 1 Introduction to games developmentLecture 1 Introduction to games development
Lecture 1 Introduction to games development
 
May Marketo Masterclass, London MUG May 22 2024.pdf
May Marketo Masterclass, London MUG May 22 2024.pdfMay Marketo Masterclass, London MUG May 22 2024.pdf
May Marketo Masterclass, London MUG May 22 2024.pdf
 
Globus Compute wth IRI Workflows - GlobusWorld 2024
Globus Compute wth IRI Workflows - GlobusWorld 2024Globus Compute wth IRI Workflows - GlobusWorld 2024
Globus Compute wth IRI Workflows - GlobusWorld 2024
 
Exploring Innovations in Data Repository Solutions - Insights from the U.S. G...
Exploring Innovations in Data Repository Solutions - Insights from the U.S. G...Exploring Innovations in Data Repository Solutions - Insights from the U.S. G...
Exploring Innovations in Data Repository Solutions - Insights from the U.S. G...
 
Navigating the Metaverse: A Journey into Virtual Evolution"
Navigating the Metaverse: A Journey into Virtual Evolution"Navigating the Metaverse: A Journey into Virtual Evolution"
Navigating the Metaverse: A Journey into Virtual Evolution"
 
How Recreation Management Software Can Streamline Your Operations.pptx
How Recreation Management Software Can Streamline Your Operations.pptxHow Recreation Management Software Can Streamline Your Operations.pptx
How Recreation Management Software Can Streamline Your Operations.pptx
 
Automated software refactoring with OpenRewrite and Generative AI.pptx.pdf
Automated software refactoring with OpenRewrite and Generative AI.pptx.pdfAutomated software refactoring with OpenRewrite and Generative AI.pptx.pdf
Automated software refactoring with OpenRewrite and Generative AI.pptx.pdf
 
Providing Globus Services to Users of JASMIN for Environmental Data Analysis
Providing Globus Services to Users of JASMIN for Environmental Data AnalysisProviding Globus Services to Users of JASMIN for Environmental Data Analysis
Providing Globus Services to Users of JASMIN for Environmental Data Analysis
 
In 2015, I used to write extensions for Joomla, WordPress, phpBB3, etc and I ...
In 2015, I used to write extensions for Joomla, WordPress, phpBB3, etc and I ...In 2015, I used to write extensions for Joomla, WordPress, phpBB3, etc and I ...
In 2015, I used to write extensions for Joomla, WordPress, phpBB3, etc and I ...
 
Innovating Inference - Remote Triggering of Large Language Models on HPC Clus...
Innovating Inference - Remote Triggering of Large Language Models on HPC Clus...Innovating Inference - Remote Triggering of Large Language Models on HPC Clus...
Innovating Inference - Remote Triggering of Large Language Models on HPC Clus...
 
Text-Summarization-of-Breaking-News-Using-Fine-tuning-BART-Model.pptx
Text-Summarization-of-Breaking-News-Using-Fine-tuning-BART-Model.pptxText-Summarization-of-Breaking-News-Using-Fine-tuning-BART-Model.pptx
Text-Summarization-of-Breaking-News-Using-Fine-tuning-BART-Model.pptx
 
BoxLang: Review our Visionary Licenses of 2024
BoxLang: Review our Visionary Licenses of 2024BoxLang: Review our Visionary Licenses of 2024
BoxLang: Review our Visionary Licenses of 2024
 
Graspan: A Big Data System for Big Code Analysis
Graspan: A Big Data System for Big Code AnalysisGraspan: A Big Data System for Big Code Analysis
Graspan: A Big Data System for Big Code Analysis
 
Vitthal Shirke Java Microservices Resume.pdf
Vitthal Shirke Java Microservices Resume.pdfVitthal Shirke Java Microservices Resume.pdf
Vitthal Shirke Java Microservices Resume.pdf
 
A Study of Variable-Role-based Feature Enrichment in Neural Models of Code
A Study of Variable-Role-based Feature Enrichment in Neural Models of CodeA Study of Variable-Role-based Feature Enrichment in Neural Models of Code
A Study of Variable-Role-based Feature Enrichment in Neural Models of Code
 
Top 7 Unique WhatsApp API Benefits | Saudi Arabia
Top 7 Unique WhatsApp API Benefits | Saudi ArabiaTop 7 Unique WhatsApp API Benefits | Saudi Arabia
Top 7 Unique WhatsApp API Benefits | Saudi Arabia
 
openEuler Case Study - The Journey to Supply Chain Security
openEuler Case Study - The Journey to Supply Chain SecurityopenEuler Case Study - The Journey to Supply Chain Security
openEuler Case Study - The Journey to Supply Chain Security
 

Android 101 - Building a simple app with Kotlin in 90 minutes

  • 1. ANDROID 101 - BUILDING A SIMPLE APP WITH KOTLIN IN 90 MINUTES KAI KOENIG (@AGENTK)
  • 2. HELLO HELLO I’m Kate! I’m an { Android Developer | GDG Organiser | Carpenter | 
 Backup Mum to all my neighbours cats | …} Find me on Twitter: @Mistyepd and I’m Kai! I’m a { Software Engineer | Pilot | GDG Organiser | 
 Gamer | Dad to 1 cat and 3 chickens | … } Find me on Twitter: @AgentK
  • 4. AGENDA ▸ What is Kotlin? ▸ Language idioms & concepts ▸ Kotlin and Android ▸ Anko DSL
  • 8. WHAT IS KOTLIN? SOME FUNDAMENTALS ▸ Statically typed programming language for the JVM and Android ▸ Started as internal language “Project Kotlin” at Jetbrains in 2010 ▸ Now: Open-Source, Apache License ▸ Kotlin SDK plus tool support for IntelliJ, Android Studio, Eclipse ▸ Named after an island in the Gulf of Finland
  • 9. WHAT IS KOTLIN? MOTIVATION FOR KOTLIN ▸ The Java platform is awesome, but it has its issues: ▸ sometimes tied to backwards/legacy compatibility ▸ can be a very verbose language and produce bloated code ▸ type system has various flaws ▸ Kotlin aims to fix a lot of those issues ▸ compiles to Java 6 byte code therefore caters well for Android runtimes
  • 11. LANGUAGE IDIOMS & CONCEPTS OVERVIEW ▸ Immutability ▸ String templates & Enum classes ▸ Null safety ▸ Properties and Fields ▸ Type inference and casts ▸ Data classes ▸ Syntactic sugar (loops, ranges etc) ▸ Extension functions ▸ Lambdas ▸ Collection API ▸ Type-safe builders ▸ Java-Kotlin-Interop
  • 12. LANGUAGE IDIOMS & CONCEPTS IMMUTABILITY ▸ Built-in support for mutable and immutable variables, properties and fields ▸ Keywords var and val ▸ val - immutable (recommended) ▸ var - mutable ▸ Similar concept applies for class properties, val creates getters, var creates getters and setters (more later) val a: Int = 1 val b = 1 val c: Int c = 1 var x = 23 x += 1
  • 13. LANGUAGE IDIOMS & CONCEPTS STRING TEMPLATES & ENUM CLASSES (I) ▸ Kotlin Strings can contain template expressions ▸ String templates start with a $ character and ▸ can contain simple references such as $s, as well as ▸ complex expressions in curly braces: 
 ${s.length} val s = "abc" val str = "$s.length is ${s.length}" Output: abc.length is 3
  • 14. LANGUAGE IDIOMS & CONCEPTS STRING TEMPLATES & ENUM CLASSES (II) ▸ Kotlin has a dedicated and expressive enum class ▸ Can be used very nicely in conjunction with String templates enum class Locale(val hello: String) { DE_DE("Hallo"), EN_NZ("Hello"), MI_NZ("Kia Ora") } class Customer(val firstName:String, val lastName:String, val locale: Locale = Locale.DE_DE) { fun sayHello() = println( "${locale.hello}, $firstName $lastName") } fun main(args : Array<String>) { val myCustomer = Customer("Sandra", "Musterfrau", Locale.MI_NZ) myCustomer.sayHello() }
  • 15. LANGUAGE IDIOMS & CONCEPTS NULL SAFETY ▸ Motivation: A better way to deal with NPEs ▸ Kotlin differentiates nullable types from non- nullable types by adding a ? to the type: ▸ String: no nullable ▸ String?: nullable ▸ Handle manually ▸ Use Safe Call operator ?. ▸ Use the !! operator to allow/trigger a NPE // Won't compile var lastName: String = null // Will compile var lastNameNullable: String? = null // Will also not compile println(lastNameNullable.length) // Option 1 (-1) println(if (lastNameNullable != null) lastNameNullable.length else -1) // Option 2 (null) println(lastNameNullable?.length) // Option 3 (NPE) println(lastNameNullable!!.length)
  • 16. LANGUAGE IDIOMS & CONCEPTS PROPERTIES AND FIELDS ▸ Kotlin classes have mutable or immutable properties ▸ Default getter/setters for properties, can be customised ▸ An automated backing field can be provided by the compiler (if required) ▸ Alternative: use an explicit backing property var counter = 0 set(value) { if (value >= 0) field = value } public class Address { public var name: String = ... public var street: String = ... public var city: String = ... public var state: String? = ... public var zip: String = ... }
  • 17. LANGUAGE IDIOMS & CONCEPTS TYPE INFERENCE AND CASTS (I) ▸ When possible, Kotlin will infer the type of variables ▸ Explicit conversions, type widening and inference ▸ Smaller types are not subtypes of bigger types, no implicit conversion ▸ Types are often inferred from the context val b: Byte = 1 // This won't work val i: Int = b // This will val i: Int = b.toInt() val l: Long = 1L + 3
  • 18. LANGUAGE IDIOMS & CONCEPTS TYPE INFERENCE AND CASTS (II) ▸ is or !is checks if an object adheres to a certain type ▸ Smart cast: Compiler tracks is-expressions for immutable values ▸ works for val local variables and private, internal or in-module performed casts ▸ works for var local variables if the variable hasn’t been modified between check and usage, never for var properties fun whatIs(x: Any) { when (x) { is Int -> println(x + 42) is String -> println(x.length) is IntArray -> println(x.sum()) } } whatIs(4) // 46 whatIs("4") // 1 whatIs(intArrayOf(1,2,3,4,5)) // 15
  • 19. LANGUAGE IDIOMS & CONCEPTS DATA CLASSES ▸ The POJOs/Beans of other languages ▸ Data classes implicitly create: ▸ getters/setters (non-data classes have those too) - recommend to use val as often as possible. ▸ useful implementations for equals(), hashCode(), toString(), copy() ▸ copy() has default parameters and can be used to alter a copy data class ChromeEncryptedPayload( val encryptedPayload: String, val encryptionHeader: String, val cryptoKeyHeader: String) val pl = ChromeEncryptedPayload( encryptedPayload = "...", encryptionHeader = "...", cryptoKeyHeader = "...") val anotherPl = pl.copy( encryptedPayload = "...")
  • 20. LANGUAGE IDIOMS & CONCEPTS EXTENSION FUNCTIONS ▸ Allow adding new functionality to a class without inheritance or Decorators ▸ Kotlin has extension functions as well as extension properties ▸ Resolved statically, don’t actually modify the class (excellent example why this has to be the case at http:// goo.gl/EN6bTs fun Int.sum(otherInt: Int): Int = this + otherInt 3.sum(7) fun Activity.toast(message: CharSequence, duration: Int = TOAST.LENGTH_SHORT) { Toast.makeText(this, message, duration).show() } // In onCreate of an Activity override fun onCreate(...) { ... toast("Hi there") ... }
  • 21. LANGUAGE IDIOMS & CONCEPTS LAMBDAS ▸ Anonymous function or “function literal”, closely related to the ideas of Higher-Order-Functions val sum = { x: Int, y: Int -> x + y } val sum: (Int, Int) -> Int = { x, y -> x + y } private fun convertPetListToDomain(list: List<Pet>): List<PetDomain> { return list.map { convertPetItemToDomain(it) } } private fun convertPetItemToDomain(pet: Pet): PetDomain { return PetDomain(pet.age,pet.size,pet.id,pet.name,pet.sex,pet.breed) }
  • 22. LANGUAGE IDIOMS & CONCEPTS TYPE-SAFE BUILDERS (I) ▸ Builders are a very popular approach in Groovy to define data in a declarative way ▸ Often used for: ▸ generating XML or JSON ▸ UI layout (Swing components) etc ▸ In Kotlin, builders even can be type- checked JsonBuilder builder = new JsonBuilder() builder.records { car { name 'HSV Maloo' make 'Holden' year 2006 country 'Australia' } } String json = JsonOutput.prettyPrint (builder.toString())
  • 23. LANGUAGE IDIOMS & CONCEPTS TYPE-SAFE BUILDERS (II) ▸ html() is a function with a lambda as an argument (init) ▸ init’s type is a function type with receiver, this allows you to: ▸ pass receiver (of type HTML) to function ▸ call members of instance inside the function fun result(args: Array<String>) = html { head { title {”HTML in Kotlin"} } body { ... } } fun html(init: HTML.() -> Unit): HTML { val html = HTML() html.init() return html }
  • 24. LANGUAGE IDIOMS & CONCEPTS TYPE-SAFE BUILDERS (III) ▸ HTML class has functions to build the head and the body elements of the DSL. ▸ Not shown: classes further down in the hierarchy: ▸ Head, Body etc. ▸ Complete HTML builder example at: http://goo.gl/TndcC9 class HTML { ... fun head(headBuilder: Head.() -> Unit) { head = Head() head?.headBuilder() } fun body(bodyBuilder: Body.() -> Unit) { body = Body() body?.bodyBuilder() } }
  • 25. LANGUAGE IDIOMS & CONCEPTS JAVA-KOTLIN-INTEROP ▸ Java and Kotlin are fully interoperable from an integration point of view ▸ Your Java code can call and use Kotlin code ▸ Your Kotlin code can call and use Java code ▸ The latter is in particular useful because it means you can continue to use pretty much any existing Android/Java library ▸ Check out Hendrik Kokocinski’s sample Kotlin app that uses all kinds of well known Android/Java libs: https://goo.gl/xdYqf5
  • 26. LANGUAGE IDIOMS & CONCEPTS OVERVIEW ▸ Immutability ▸ String templates & Enum classes ▸ Null safety ▸ Properties and Fields ▸ Type inference and casts ▸ Data classes ▸ Syntactic sugar (loops, ranges etc) ▸ Extension functions ▸ Lambdas ▸ Collection API ▸ Type-safe builders ▸ Java-Kotlin-Interop
  • 28. APP STEP 1 - KOTLIN SETUP ▸ Setup Kotlin Plugin and tooling ▸ Automated vs. manual
  • 29. APP STEP 2 - REFACTOR JAVA -> KOTLIN ▸ Kotlin Source Path
  • 30. APP STEP 3 - KOTLIN ANDROID EXTENSIONS ▸ Finding views with KAE (built into the plugin)
  • 31. APP STEP 4 - MORE KAE ▸ KAE Click handler - compare to classic Kotlin code ▸ Lambdas
  • 32. APP STEP 5 - BUTTERKNIFE ▸ View Bindings with Butterknife in Kotlin ▸ KAPT setup
  • 33. APP STEP 6 - RECYCLERVIEW AND SOME DATA ▸ Adding Adapter and RecyclerView ▸ Displaying hardcoded data for now
  • 34. APP STEP 7 - DATA (I) ▸ Loading and returning some hard JSON sample data ▸ Companion object ▸ No UI changes, use debugger in MainActivity
  • 35. APP STEP 8 - DATA (II) / GSON PARSING ▸ Kotlin data classes ▸ GSON parsing ▸ String templates ▸ No UI changes, use debugger in MainActivity
  • 36. APP STEP 9 - ARCHITECTURE ▸ Command pattern ▸ Introducing Anko for async ▸ More String templates ▸ with ▸ Interface ▸ .map
  • 38. ANKO DSL WHAT IS A DSL? ▸ Domain-Specific Language ▸ Limited expressiveness: ▸ DSLs are usually not general-purpose languages ▸ strongly focussed on a particular domain ▸ examples: SQL, Ant XML, XSLT, Gradle etc.
  • 39. ANKO DSL A DSL FOR LAYOUTS ▸ The most important element of Anko is the Layout DSL ▸ Idea: replace XML layout definitions by Kotlin code - without having to build the layout in a fully programmatic sense ▸ Modular: as we’re talking about UI/Layout, it’s very important to select the right library for your minSDKVersion ▸ Extensible: you can add your own DSL elements for custom UI controls
  • 40. ANKO DSL LAYOUT XML <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent"> <EditText android:layout_width="match_parent" android:gravity="center" android:text="@string/empty_todos_message" android:layout_weight="7" android:layout_height="wrap_content" /> <Button android:layout_width="match_parent" android:layout_weight="1" android:text="Say Hello" android:layout_height="0dp" /> </LinearLayout>
  • 41. ANKO DSL PROGRAMMATIC LAYOUT IN KOTLIN val act = this val layout = LinearLayout(act) layout.orientation = LinearLayout.VERTICAL val name = EditText(act) val button = Button(act) button.text = "Say Hello" button.setOnClickListener { Toast.makeText(act, "Hello, ${name.text}!", Toast.LENGTH_SHORT).show() } layout.addView(name) layout.addView(button)
  • 42. ANKO DSL ANKO DSL verticalLayout { val name = editText() button("Say Hello") { onClick { toast("Hello, ${name.text}!") } } }
  • 43. ANKO DSL ANKO DSL INTERNALS ▸ Anko DSL example from previous slide looks very similar to the earlier HTML builder example ▸ Anko uses extension functions arranged into type-safe builders and lambdas ▸ You don’t have to write all those extensions by hand though - Anko generates them based on the Android SDK’s android.jar
  • 44. ANKO DSL GETTING STARTED WITH ANKO DSL (I) ▸ Depending on minSdkVersion of project, import:
 compile "org.jetbrains.anko:anko-sdk{15|19|21|23}:0.9" ▸ If the project uses an Android Support library, import matching Anko library:
 compile "org.jetbrains.anko:anko-recyclerview-v7:0.9"
  • 45. ANKO DSL GETTING STARTED WITH ANKO DSL (II) ▸ General approach: ▸ Anko DSL automatically becomes available in onCreate() in an Activity ▸ no need for setContentView(), Anko DSL also automatically sets the content view for activities override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) verticalLayout { padding = dip(30) editText { hint = "Name" textSize = 24f } editText { hint = "Password" textSize = 24f } button("Login") { textSize = 26f } } }
  • 46. ANKO DSL ANKO DSL IN FRAGMENTS ▸ In fragments, use 
 onCreateView(…) ▸ Returns UI {…}.view: ▸ mandatory before Anko 0.8 ▸ works well for Fragments ▸ createTodo() is a fragment-private method override fun onCreateView(inflater: LayoutInflater?, container: ViewGroup?, savedInstanceState: Bundle?): View? { return UI { verticalLayout { padding = dip(24) var title = editText { id = R.id.title hintResource = R.string.hint } ... button { id = R.id.add textResource = R.string.add onClick { view -> createTodo(title, desc) } } } }.view }
  • 47. ANKO DSL ANKO COMPONENTS (I) ▸ Often it’s nicer to have UI code separated from onCreate or other livecycle methods ▸ AnkoComponent helps organising your UI code in their own classes
  • 48. ANKO DSL ANKO COMPONENTS (II) override fun onCreateView(...)= EditFragmentUI().createView(AnkoContext.create(ctx,this)) class EditFragmentUI : AnkoComponent<EditFragment> { override fun createView(ui: AnkoContext<EditFragment>) = with(ui) { verticalLayout { padding = dip(24) var title = editText { id = R.id.title hintResource = R.string.hint } ... button { id = R.id.add textResource = R.string.add onClick { view -> ui.owner.createTodoFrom(title, desc) } } } } }
  • 49. ANKO DSL ANKO COMPONENTS (III) ▸ Anko Preview plugin for AnkoComponent layouts ▸ Get it here: http://goo.gl/5CVmAA ▸ Can preview layouts and convert XML to Anko DSL ▸ Can be fiddly to get going with AS, Kotlin plugin versions
  • 50. ANKO DSL EXTENDING ANKOS DSL FUNCTIONALITY (I) ▸ Multiple ways to do this: ▸ insert an existing XML layout into an Anko DSL declaration:
 ▸ adding new DSL elements to the language include<View>(R.layout.mylayout) { ... } inline fun ViewManager.customView(theme: Int = 0) = customView(theme) {} inline fun ViewManager.customView(theme: Int = 0, init: CustomView.() -> Unit) = ankoView({ CustomView(it) }, theme, init) inline fun Activity.customView(theme: Int = 0) = customView(theme) {} inline fun Activity.customView(theme: Int = 0, init: CustomView.() -> Unit) = ankoView({ CustomView(it) }, theme, init)
  • 51. ANKO DSL EXTENDING ANKOS DSL FUNCTIONALITY (II) ▸ Extending Anko’s DSL to support your own custom view groups is currently rather painful ▸ Essentially it comes down to .lparams (for layout purposes) not being easily accessible ▸ More here: ▸ http://goo.gl/qpb3SL ▸ http://goo.gl/tMHs2c ▸ Fix targeted for Anko 0.9.1
  • 52. THE HIDDEN PARTS OF ANKO
  • 53. THE HIDDEN PARTS OF ANKO BUT THERE’S MORE ▸ Intent wrappers for various purposes: e.g. sendSMS(number, [text]) ▸ Intent builders ▸ Service shortcuts ▸ Configuration qualifiers: configuration(screenSize = ScreenSize.LARGE, orientation = Orientation.LANDSCAPE) { … } ▸ Asynchronous tasks ▸ SQLLite
  • 54. THE HIDDEN PARTS OF ANKO INTENT WRAPPERS AND SERVICE SHORTCUTS ▸ Anko provides wrappers for commonly used Intents: ▸ makeCall(number), sendSMS(number, text), browse(url) etc. ▸ Shortcuts to Android services: ▸ notificationManager, displayManager, sensorManager etc. ▸ Useful, but both not major features of Anko
  • 55. THE HIDDEN PARTS OF ANKO INTENT BUILDERS ▸ Syntactic sugar to cut down the amount of code needed to start a new activity val intent = Intent(this, javaClass<MyActivity>()) intent.putExtra("customerId", 4711) intent.putExtra("country", "NZ") startActivity(intent) startActivity(Intent(this, MyActivity::class.java). putExtra("customerId", 4711).putExtra("country", "NZ")) startActivity<MyActivity>("customerId" to 4711, "country" to "NZ")
  • 56. THE HIDDEN PARTS OF ANKO CONFIGURATION QUALIFIERS ▸ “CSS Media Queries for Android” ▸ Screen features: ▸ screenSize, density, orientation, long, 
 nightMode, rightToLeft, smallestWidth ▸ SDK versions: ▸ fromSdk, sdk ▸ Other: ▸ language, uiMode configuration(screenSize = ScreenSize.LARGE, orientation = Orientation.LANDSCAPE) { /* This code will be only executed if the screen is large and its orientation is landscape */ }
  • 57. THE HIDDEN PARTS OF ANKO ASYNC DSL ▸ Does anyone enjoy working with AsyncTasks? ▸ Anko: async and asyncResult (return future respectively future with result) async() { val result = PetFindCommand("90210","cat").execute() uiThread { animalList.adapter = AnimalListAdapter(result, object: AnimalListAdapter.ItemClickListener{ override fun invoke(pet:Pet) { toast(pet.name) } } ) } }
  • 58. THE HIDDEN PARTS OF ANKO SQLITE (I) ▸ Working with SQLite usually requires a lot of boilerplate code and try/catch- structures, issues around concurrency, dealing with cached code and references etc. ▸ Anko aims to make that easier ▸ Dependency: compile ‘org.jetbrains.anko:anko-sqlite:0.9' ▸ Setup class extending ManagedSQLiteOpenHelper in your code
  • 59. THE HIDDEN PARTS OF ANKO SQLITE (II) ▸ database.use ensures DB is opened and closed correctly ▸ Asynchronous use of the DB is possible through Anko’s async DSL ▸ Important: There can still be SQLiteExceptions when handling SQL code - Anko doesn’t abstract those. ▸ Handling of cursors and parsing data via lambdas database.use { createTable("Customer", ifNotExists = true, "id" to INTEGER + PRIMARY_KEY + UNIQUE, "name" to TEXT, "photo" to BLOB) }
  • 60. APP STEP 10 - CLICK ON LIST ▸ Adapter/RecyclerView click handler changes ▸ when-statement
  • 61. APP STEP 11 - EXCEPTIONS ▸ Exception handler in Anko
  • 62. APP STEP 12 - ANKO DSL ▸ Anko layout for main view ▸ Removing layout XML and replacing it with Anko DSL
  • 63. APP STEP 13 - ANKO COMPONENTS ▸ Refactoring into Anko component
  • 64. APP STEP 14 ▸ Mini refactoring for better testing ▸ jUnit tests in Kotlin
  • 65. APP STEP 15 ▸ Using Spek for BDD testing
  • 66. APP IDEAS ▸ Add second Activity or Fragment to display and edit details ▸ Change layout to ConstraintLayout ▸ Use Kotson instead of Gson ▸ Store data locally ▸ Change RecyclerView to Anko Layout DSL ▸ Use Butterknife instead of Kotterknife ▸ Write some proper tests ▸ Try Android integration tests
  • 69. RESOURCES RESOURCES ▸ Kotlin: http://kotlinlang.org ▸ Anko: https://github.com/Kotlin/anko ▸ Kotter Knife: https://github.com/JakeWharton/kotterknife ▸ Spek: http://jetbrains.github.io/spek/ ▸ Kotson: https://github.com/SalomonBrys/Kotson
  • 70. RESOURCES GET IN TOUCH Kai Koenig Email: kai@ventego-creative.co.nz Twitter: @AgentK Kate Henderson Email: hi@kate.nz Twitter: @Mistyepd