O slideshow foi denunciado.
Utilizamos seu perfil e dados de atividades no LinkedIn para personalizar e exibir anúncios mais relevantes. Altere suas preferências de anúncios quando desejar.

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

Slides for an introductory Android-Kotlin workshop as part of the Summer of Tech 2018 program.

Livros relacionados

Gratuito durante 30 dias do Scribd

Ver tudo

Audiolivros relacionados

Gratuito durante 30 dias do Scribd

Ver tudo
  • Seja o primeiro a comentar

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

  1. 1. ANDROID 101 - BUILDING A SIMPLE APP WITH KOTLIN IN 90 MINUTES KAI KOENIG (@AGENTK)
  2. 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
  3. 3. HELLO CODE https://github.com/TheRealAgentK/ SummerOfTech-Android-2018
  4. 4. AGENDA ▸ What is Kotlin? ▸ Language idioms & concepts ▸ Kotlin and Android ▸ Anko DSL
  5. 5. MORE GDG WELLINTON
  6. 6. MORE WELLINGTON.KT
  7. 7. WHAT IS KOTLIN?
  8. 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. 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
  10. 10. LANGUAGE IDIOMS & CONCEPTS https://www.flickr.com/photos/geraldford/6976818221/
  11. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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
  27. 27. KOTLIN AND ANDROID https://realm.io/assets/img/news/tutorial-kotlin-anko-cover.png
  28. 28. APP STEP 1 - KOTLIN SETUP ▸ Setup Kotlin Plugin and tooling ▸ Automated vs. manual
  29. 29. APP STEP 2 - REFACTOR JAVA -> KOTLIN ▸ Kotlin Source Path
  30. 30. APP STEP 3 - KOTLIN ANDROID EXTENSIONS ▸ Finding views with KAE (built into the plugin)
  31. 31. APP STEP 4 - MORE KAE ▸ KAE Click handler - compare to classic Kotlin code ▸ Lambdas
  32. 32. APP STEP 5 - BUTTERKNIFE ▸ View Bindings with Butterknife in Kotlin ▸ KAPT setup
  33. 33. APP STEP 6 - RECYCLERVIEW AND SOME DATA ▸ Adding Adapter and RecyclerView ▸ Displaying hardcoded data for now
  34. 34. APP STEP 7 - DATA (I) ▸ Loading and returning some hard JSON sample data ▸ Companion object ▸ No UI changes, use debugger in MainActivity
  35. 35. APP STEP 8 - DATA (II) / GSON PARSING ▸ Kotlin data classes ▸ GSON parsing ▸ String templates ▸ No UI changes, use debugger in MainActivity
  36. 36. APP STEP 9 - ARCHITECTURE ▸ Command pattern ▸ Introducing Anko for async ▸ More String templates ▸ with ▸ Interface ▸ .map
  37. 37. ANKO DSL
  38. 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. 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. 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. 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. 42. ANKO DSL ANKO DSL verticalLayout { val name = editText() button("Say Hello") { onClick { toast("Hello, ${name.text}!") } } }
  43. 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. 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. 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. 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. 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. 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. 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. 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. 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. 52. THE HIDDEN PARTS OF ANKO
  53. 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. 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. 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. 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. 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. 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. 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. 60. APP STEP 10 - CLICK ON LIST ▸ Adapter/RecyclerView click handler changes ▸ when-statement
  61. 61. APP STEP 11 - EXCEPTIONS ▸ Exception handler in Anko
  62. 62. APP STEP 12 - ANKO DSL ▸ Anko layout for main view ▸ Removing layout XML and replacing it with Anko DSL
  63. 63. APP STEP 13 - ANKO COMPONENTS ▸ Refactoring into Anko component
  64. 64. APP STEP 14 ▸ Mini refactoring for better testing ▸ jUnit tests in Kotlin
  65. 65. APP STEP 15 ▸ Using Spek for BDD testing
  66. 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
  67. 67. MORE GDG WELLINTON
  68. 68. MORE WELLINGTON.KT
  69. 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. 70. RESOURCES GET IN TOUCH Kai Koenig Email: kai@ventego-creative.co.nz Twitter: @AgentK Kate Henderson Email: hi@kate.nz Twitter: @Mistyepd

    Seja o primeiro a comentar

    Entre para ver os comentários

  • gutoxp

    Apr. 18, 2018
  • SirupangiNikhil

    Apr. 19, 2018
  • mariadavisc

    Apr. 20, 2018
  • hilmy1010

    May. 1, 2018
  • Bugraptors

    Oct. 29, 2018

Slides for an introductory Android-Kotlin workshop as part of the Summer of Tech 2018 program.

Vistos

Vistos totais

553

No Slideshare

0

De incorporações

0

Número de incorporações

1

Ações

Baixados

18

Compartilhados

0

Comentários

0

Curtir

5

×