ANKO THE ULTIMATE NINJA OF KOTLIN LIBRARIES? AGENDA What are - - PowerPoint PPT Presentation
ANKO THE ULTIMATE NINJA OF KOTLIN LIBRARIES? AGENDA What are - - PowerPoint PPT Presentation
KAI KOENIG (@AGENTK) 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 WHAT ARE
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
WHAT ARE KOTLIN AND ANKO?
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
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
- r 7 (if we’re lucky…) and you can’t use all the new, shiny features from Java 8
and soon Java 9 and 10
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 = "}") }
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
ANKO-RELATED IDIOMS & LANGUAGE PATTERNS
https://www.flickr.com/photos/geraldford/6976818221/
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
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)
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 }
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 +
- therInt
3.sum(7) fun Activity.toast(message: CharSequence, duration: Int = TOAST.LENGTH_SHORT) { Toast.makeText(this, message, duration).show() } // In onCreate of an Activity
- verride fun onCreate(...) {
... toast("Hi there") ... }
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())
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 }
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() } }
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
ANKO DSL
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.
ANKO DSL
MORE ON DSL CONCEPTS
▸ Increased level of abstraction ▸ What vs. How ▸ Common discussion: are DSLs code or data? ▸ Interpretation vs. code generation
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") {
- nClick { 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
- verride 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
- nCreateView(…)
▸ Returns UI {…}.view: ▸ mandatory before Anko 0.8 ▸ works well for Fragments ▸ createTodo() is a fragment-private
method
- verride 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
- nClick { 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)
class EditFragmentUI : AnkoComponent<EditFragment> {
- verride 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
- nClick { view -> ui.owner.createTodoFrom(title, desc) }
} } } }
- verride fun onCreateView(...)= EditFragmentUI().createView(AnkoContext.create(ctx,this))
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,
- rientation = 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,
- rientation =
Orientation.LANDSCAPE) { /* This code will be only executed if the screen is large and its
- rientation 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,
- bject: AnimalListAdapter.ItemClickListener{
- verride 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) }
ANKO VS THE REST?
https://www.flickr.com/photos/sillygwailo/5990089210/
ANKO VS THE REST?
ANKO AND OTHER KOTLIN LIBRARIES
▸ KAndroid ▸ Kovenant
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
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
ANKO VS THE REST?
KANDROID EXAMPLES
runDelayed(1000) { // delayed execution } runDelayedOnUiThread(5000) { // delayed UI update } toApi(16, inclusive = true) { // handle devices running older APIs }
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
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
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 }
ANKO VS THE REST?
KOVENANT EXAMPLES (II)
promiseOnUi { // do some UI preparation } then { // the actual work } successUi { // update UI }
FINAL THOUGHTS
https://www.flickr.com/photos/brickset/16099265973/
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
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
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
FINAL THOUGHTS
GET IN TOUCH
Kai Koenig Email: kai@ventego-creative.co.nz Twitter: @AgentK