54
ANKO THE ULTIMATE NINJA OF KOTLIN LIBRARIES? KAI KOENIG (@AGENTK)

Anko - The Ultimate Ninja of Kotlin Libraries?

Embed Size (px)

Citation preview

Page 1: Anko - The Ultimate Ninja of Kotlin Libraries?

ANKO THE ULTIMATE NINJA OF KOTLIN LIBRARIES?

KAI KOENIG (@AGENTK)

Page 2: Anko - The Ultimate Ninja of Kotlin Libraries?

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

Page 3: Anko - The Ultimate Ninja of Kotlin Libraries?

WHAT ARE KOTLIN AND ANKO?

Page 4: Anko - The Ultimate Ninja of Kotlin Libraries?

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

Page 5: Anko - The Ultimate Ninja of Kotlin Libraries?

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

Page 6: Anko - The Ultimate Ninja of Kotlin Libraries?

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 = "}") }

Page 7: Anko - The Ultimate Ninja of Kotlin Libraries?

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

Page 8: Anko - The Ultimate Ninja of Kotlin Libraries?

ANKO-RELATED IDIOMS & LANGUAGE PATTERNS

https://www.flickr.com/photos/geraldford/6976818221/

Page 9: Anko - The Ultimate Ninja of Kotlin Libraries?

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

Page 10: Anko - The Ultimate Ninja of Kotlin Libraries?

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)

Page 11: Anko - The Ultimate Ninja of Kotlin Libraries?

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 }

Page 12: Anko - The Ultimate Ninja of Kotlin Libraries?

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") ... }

Page 13: Anko - The Ultimate Ninja of Kotlin Libraries?

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())

Page 14: Anko - The Ultimate Ninja of Kotlin Libraries?

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 }

Page 15: Anko - The Ultimate Ninja of Kotlin Libraries?

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() } }

Page 16: Anko - The Ultimate Ninja of Kotlin Libraries?

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

Page 17: Anko - The Ultimate Ninja of Kotlin Libraries?

ANKO DSL

Page 18: Anko - The Ultimate Ninja of Kotlin Libraries?

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.

Page 19: Anko - The Ultimate Ninja of Kotlin Libraries?

ANKO DSL

MORE ON DSL CONCEPTS

▸ Increased level of abstraction

▸ What vs. How

▸ Common discussion: are DSLs code or data?

▸ Interpretation vs. code generation

Page 20: Anko - The Ultimate Ninja of Kotlin Libraries?

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

Page 21: Anko - The Ultimate Ninja of Kotlin Libraries?

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>

Page 22: Anko - The Ultimate Ninja of Kotlin Libraries?

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)

Page 23: Anko - The Ultimate Ninja of Kotlin Libraries?

ANKO DSL

ANKO DSL

verticalLayout { val name = editText() button("Say Hello") { onClick { toast("Hello, ${name.text}!") } } }

Page 24: Anko - The Ultimate Ninja of Kotlin Libraries?

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

Page 25: Anko - The Ultimate Ninja of Kotlin Libraries?

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"

Page 26: Anko - The Ultimate Ninja of Kotlin Libraries?

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 } } }

Page 27: Anko - The Ultimate Ninja of Kotlin Libraries?

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 }

Page 28: Anko - The Ultimate Ninja of Kotlin Libraries?

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

Page 29: Anko - The Ultimate Ninja of Kotlin Libraries?

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))

Page 30: Anko - The Ultimate Ninja of Kotlin Libraries?

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

Page 31: Anko - The Ultimate Ninja of Kotlin Libraries?

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)

Page 32: Anko - The Ultimate Ninja of Kotlin Libraries?

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

Page 33: Anko - The Ultimate Ninja of Kotlin Libraries?

THE HIDDEN PARTS OF ANKO

Page 34: Anko - The Ultimate Ninja of Kotlin Libraries?

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

Page 35: Anko - The Ultimate Ninja of Kotlin Libraries?

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

Page 36: Anko - The Ultimate Ninja of Kotlin Libraries?

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")

Page 37: Anko - The Ultimate Ninja of Kotlin Libraries?

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 */ }

Page 38: Anko - The Ultimate Ninja of Kotlin Libraries?

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) } } ) } }

Page 39: Anko - The Ultimate Ninja of Kotlin Libraries?

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

Page 40: Anko - The Ultimate Ninja of Kotlin Libraries?

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) }

Page 41: Anko - The Ultimate Ninja of Kotlin Libraries?

ANKO VS THE REST?

https://www.flickr.com/photos/sillygwailo/5990089210/

Page 42: Anko - The Ultimate Ninja of Kotlin Libraries?

ANKO VS THE REST?

ANKO AND OTHER KOTLIN LIBRARIES

▸ KAndroid

▸ Kovenant

Page 43: Anko - The Ultimate Ninja of Kotlin Libraries?

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

Page 44: Anko - The Ultimate Ninja of Kotlin Libraries?

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

Page 45: Anko - The Ultimate Ninja of Kotlin Libraries?

ANKO VS THE REST?

KANDROID EXAMPLES

runDelayed(1000) { // delayed execution }

runDelayedOnUiThread(5000) { // delayed UI update }

toApi(16, inclusive = true) { // handle devices running older APIs }

Page 46: Anko - The Ultimate Ninja of Kotlin Libraries?

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

Page 47: Anko - The Ultimate Ninja of Kotlin Libraries?

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

Page 48: Anko - The Ultimate Ninja of Kotlin Libraries?

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 }

Page 49: Anko - The Ultimate Ninja of Kotlin Libraries?

ANKO VS THE REST?

KOVENANT EXAMPLES (II)

promiseOnUi { // do some UI preparation } then { // the actual work } successUi { // update UI }

Page 50: Anko - The Ultimate Ninja of Kotlin Libraries?

FINAL THOUGHTS

https://www.flickr.com/photos/brickset/16099265973/

Page 51: Anko - The Ultimate Ninja of Kotlin Libraries?

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

Page 52: Anko - The Ultimate Ninja of Kotlin Libraries?

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

Page 53: Anko - The Ultimate Ninja of Kotlin Libraries?

FINAL THOUGHTS

RESOURCES

▸ Kotlin: http://kotlinlang.org

▸ Anko: https://github.com/Kotlin/anko

▸ Fuel: https://github.com/kittinunf/Fuel

▸ KAndroid: https://github.com/pawegio/KAndroid

▸ Kovenant: https://github.com/mplatvoet/kovenant

Page 54: Anko - The Ultimate Ninja of Kotlin Libraries?

FINAL THOUGHTS

GET IN TOUCH

Kai Koenig

Email: [email protected]

Twitter: @AgentK