Kotlin is a new language for the JVM that aims to be a ””better Java”“. Made in-house by Jetbrains, the company behind IntelliJ IDEA and also Android Studio, it’s been in development for more than 5 years. Just a few weeks ago the final version of Kotlin 1.0 saw the light of day.
The language itself gives one so much niceness and syntactic sugar that you’d probably never want to go back to coding in Java again. Things get even better with Anko. Anko is pretty much the ultimate Ninja of Kotlin libraries. The feature it’s best know for is its Layout DSL that allows one to programatically write UI code in Kotlin. No more XML layout and no awkward piecing together of your UI through clunky Java APIs. We will look at how to use and how to extend the Layout DSL for your own requirements and then move on to Anko’s advanced, non-layout-related features:
- Intent wrappers
- Shortcuts to system services
- Asynchronous task management
- Anko SQLite and more
2. AGENDA
▸ What are Kotlin and Anko?
▸ Anko-related idioms and language concepts
▸ Anko DSL
▸ The hidden parts of Anko
▸ Anko VS The Rest
▸ Final thoughts
4. WHAT ARE KOTLIN AND ANKO?
SOME KOTLIN 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
5. WHAT ARE KOTLIN AND ANKO?
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, in particular when you have to use Java 6
or 7 (if we’re lucky…) and you can’t use all the new, shiny features from Java 8
and soon Java 9 and 10
6. WHAT ARE KOTLIN AND ANKO?
HOW DOES A SIMPLE CONVERSION LOOK LIKE?
public String listConvert(Collection<Integer> collection) {
StringBuilder sb = new StringBuilder();
sb.append("{");
Iterator<Integer> iterator = collection.iterator();
while (iterator.hasNext()) {
Integer element = iterator.next();
sb.append(element);
if (iterator.hasNext()) {
sb.append(", ");
}
}
sb.append("}");
return sb.toString();
}
fun listConvert(collection: Collection<Int>): String {
val sb = StringBuilder()
sb.append("{")
val iterator = collection.iterator()
while (iterator.hasNext()) {
val element = iterator.next()
sb.append(element)
if (iterator.hasNext()) {
sb.append(", ")
}
}
sb.append("}")
return sb.toString()
}
fun listConvertKt(collection: Collection<Int>): String {
return collection.joinToString(prefix = "{",postfix = "}")
}
7. WHAT ARE KOTLIN AND ANKO?
WHAT IS ANKO?
▸ Library to make Android development with Kotlin faster and easier
▸ Created by Jetbrains
▸ Best-known feature is Anko’s Layout DSL
▸ Some other functionality:
▸ intent and service wrappers
▸ async call handling
▸ SQLite
9. ANKO-RELATED IDIOMS & LANGUAGE PATTERNS
IDIOM AND LANGUAGE 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
10. ANKO-RELATED IDIOMS & LANGUAGE PATTERNS
DATA CLASSES
▸ The POJOs or Beans of other languages
▸ Data classes implicitly create:
▸ getters/setters (non-data classes have
those too) - recommended to use val
as often as possible.
▸ proper and 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)
11. ANKO-RELATED IDIOMS & LANGUAGE PATTERNS
PROPERTIES AND FIELDS
▸ Kotlin classes have mutable or
immutable properties
▸ An automated backing field can be
provided by the compiler (if required)
▸ Default getter/setters for properties,
can be customised
var counter = 0
set(value) {
if (value >= 0)
field = value
}
12. ANKO-RELATED IDIOMS & LANGUAGE PATTERNS
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")
...
}
13. ANKO-RELATED IDIOMS & LANGUAGE PATTERNS
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())
14. ANKO-RELATED IDIOMS & LANGUAGE PATTERNS
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
}
15. ANKO-RELATED IDIOMS & LANGUAGE PATTERNS
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
hierachy:
▸ 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()
}
}
16. ANKO-RELATED IDIOMS & LANGUAGE PATTERNS
IDIOM AND LANGUAGE 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
18. ANKO DSL
WHAT IS A DSL?
▸ Domain-Specific Language
▸ Computer programming language
▸ Limited expressiveness:
▸ DSLs are usually not general-purpose languages
▸ strongly focussed on a particular domain
▸ examples: SQL, Ant XML, XSLT, Gradle etc.
19. ANKO DSL
MORE ON DSL CONCEPTS
▸ Increased level of abstraction
▸ What vs. How
▸ Common discussion: are DSLs code or data?
▸ Interpretation vs. code generation
20. 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
22. 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)
24. 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
25. 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"
26. 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
}
}
}
27. 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
}
28. 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
29. ANKO DSL
ANKO COMPONENTS (II)
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) }
}
}
}
}
override fun onCreateView(...)= EditFragmentUI().createView(AnkoContext.create(ctx,this))
30. 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
31. 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)
32. 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
34. 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
35. 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
36. 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")
37. 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
*/
}
38. 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)
}
}
)
}
}
39. 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
40. 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)
}
41. ANKO VS THE REST?
https://www.flickr.com/photos/sillygwailo/5990089210/
42. ANKO VS THE REST?
ANKO AND OTHER KOTLIN LIBRARIES
▸ KAndroid
▸ Kovenant
43. ANKO VS THE REST?
KANDROID
▸ KAndroid is an extension library for Kotlin/Android
▸ Contains a variety of absolutely distinct and unconnected functionality
▸ Common theme: let’s get rid of boilerplate code
▸ Apache 2.0 license
44. ANKO VS THE REST?
KANDROID FEATURES
▸ View binding (again)
▸ TextWatcher
▸ SeekBar Extension
▸ SearchView Extension
▸ Shortcuts to system services
▸ Logging
▸ Dealing with Intents
▸ SDK Version API (from/to)
▸ Thread management
46. ANKO VS THE REST?
KOVENANT
▸ In a nutshell: Promises for Kotlin
▸ Very modular built, you can essentially pick and choose the artifacts of
Kovenant you’d like to use - Kovenant is not an Android-specific library
▸ Good starting set for Android: core, android, combine, jvm, functional
▸ MIT license
47. ANKO VS THE REST?
KOVENANT FEATURES
▸ Core, foundations of a promise
framework
▸ Tasks & callbacks
▸ Chaining (Then, ThenApply)
▸ Lazy promises
▸ Cancelling and voiding
▸ Combine: combines 2-20 promises
▸ Functional: adds map, bind and
apply to support more advanced
HOF constructs in Kovenant
▸ JVM: Executors and Throttles (thread
pools)
▸ Android: UI callbacks and interacting
with UI Thread
48. ANKO VS THE REST?
KOVENANT EXAMPLES (I)
task {
// some long-running thing
} success {
println("result: $it")
} fail {
println("problem: ${it.message}")
} always {
// this will always happen
}
49. ANKO VS THE REST?
KOVENANT EXAMPLES (II)
promiseOnUi {
// do some UI preparation
} then {
// the actual work
} successUi {
// update UI
}
51. FINAL THOUGHTS
MATURITY AND FUTURE
▸ Kotlin 1.0 was a big step for the language
▸ Surprisingly mature for a 1.0 release (but 5+ years in the making), full of great
concepts and idioms, getting better with each release
▸ Anko is very stable given it’s still a 0.x release
▸ Anko makes UI declaration actually pleasurable but offers way more than only a
layout DSL
▸ KAndroid offers additional extension functions, Kovenant is a full-on promises
framework
52. FINAL THOUGHTS
WHAT DID WE COVER?
▸ What are Kotlin and Anko?
▸ Anko-related idioms and language concepts
▸ Anko DSL
▸ The hidden parts of Anko
▸ Anko VS The Rest
▸ Final thoughts