Diese Präsentation wurde erfolgreich gemeldet.
Die SlideShare-Präsentation wird heruntergeladen. ×

eMan Dev Meetup: Kotlin For Android (part 03/03) 18.5.2017

Anzeige
Anzeige
Anzeige
Anzeige
Anzeige
Anzeige
Anzeige
Anzeige
Anzeige
Anzeige
Anzeige
Anzeige

Hier ansehen

1 von 71 Anzeige

Weitere Verwandte Inhalte

Diashows für Sie (20)

Ähnlich wie eMan Dev Meetup: Kotlin For Android (part 03/03) 18.5.2017 (20)

Anzeige

Weitere von eMan s.r.o. (13)

Aktuellste (20)

Anzeige

eMan Dev Meetup: Kotlin For Android (part 03/03) 18.5.2017

  1. 1. otlin For Android
  2. 2. Kotlin for Android Overview: ● Kotlin & Android ● Kotlin Android Extensions ● Anko ● Requery ● Kotpref ● PaperParcel
  3. 3. otlin for
  4. 4. Kotlin for Android ● Reduce the amount of boilerplate code you need to write ● Make your code more readable and understandable ● No more errors such as NPE ● No more findViewById() ● One language for Android & Gradle ● Interoperability ● New languge -> Kotlin is fun ● Compatible with JDK 6 -> can run on older Android devices
  5. 5. Kotlin for Android / Android Extensions Kotlin Android Extensions ● Compiler extension that allows to us replace findViewById() calls with synthetic-generated properties
  6. 6. Kotlin for Android / Android Extensions Example: <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:gravity="center" tools:context="cz.kotliners.android.extension.demo.MainActivity"> <TextView android:id="@+id/helloText" android:layout_width="wrap_content" android:layout_height="wrap_content"/> </LinearLayout>
  7. 7. Kotlin for Android / Android Extensions Example: public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); } } private TextView helloText; helloText = (TextView) findViewById(R.id.helloText); helloText.setText("Hello World!");
  8. 8. Kotlin for Android / Android Extensions Example: Add Kotlin Android Extensions Gradle plugin: // app/build.gradle apply plugin: 'com.android.application' apply plugin: 'kotlin-android' apply plugin: 'kotlin-android-extensions'
  9. 9. Kotlin for Android / Android Extensions Example: class MainActivityKotlin : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) } } helloText.setText("Hello CZ KUG!!!") import kotlinx.android.synthetic.main.activity_main.*
  10. 10. Kotlin for Android / Android Extensions Example: public final class MainActivityKotlin extends AppCompatActivity { private HashMap _$_findViewCache; protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); this.setContentView(2130968603); ((TextView)this._$_findCachedViewById(id.helloText)).setText((CharSequence)"Hello CZ KUG!!!"); } public View _$_findCachedViewById(int var1) { if(this._$_findViewCache == null) { this._$_findViewCache = new HashMap(); } View var2 = (View)this._$_findViewCache.get(Integer.valueOf(var1)); if(var2 == null) { var2 = this.findViewById(var1); this._$_findViewCache.put(Integer.valueOf(var1), var2); } return var2; } public void _$_clearFindViewByIdCache() { if(this._$_findViewCache != null) { this._$_findViewCache.clear(); } } } Bytecode
  11. 11. Anko ● Anko is a library that uses Kotlin and provides a lot of extension functions to make our Android development easier. ● It contains wrappers around the Android APIs and DSL that allows to us to replace layouts written in the XML file
  12. 12. Anko Gradle dependencies { // Anko compile "org.jetbrains.anko:anko-sdk15:$anko_version" compile "org.jetbrains.anko:anko-support-v4:$anko_version" compile "org.jetbrains.anko:anko-appcompat-v7:$anko_version" }
  13. 13. Anko - Layouts 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) verticalLayout { val name = editText() button("Say Hello") { onClick { toast("Hello, ${name.text}!") } } }
  14. 14. Anko - Layouts - Demo
  15. 15. Anko - Layouts - Demo class SignInActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) } } verticalLayout { } editText { id = R.id.usernameEditText hintResource = R.string.sign_in_username textSize = 24f } editText { id = R.id.passwordEditText hintResource = R.string.signIn_password textSize = 24f } button { id = R.id.signIn_button textResource = R.string.signIn_button } .lparams(width = matchParent, height = wrapContent) .lparams(width = matchParent, height = wrapContent) .lparams(width = matchParent, height = wrapContent)
  16. 16. Anko - Layouts - Demo class SignInActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) } } verticalLayout { } editText { id = R.id.usernameEditText hintResource = R.string.sign_in_username textSize = 24f } editText { id = R.id.passwordEditText hintResource = R.string.signIn_password textSize = 24f } button { id = R.id.signIn_button textResource = R.string.signIn_button } .lparams(width = matchParent, height = wrapContent) .lparams(width = matchParent, height = wrapContent) .lparams(width = matchParent, height = wrapContent) class SingInView : AnkoComponent<SignInActivity> { override fun createView(ui: AnkoContext<SignInActivity>) = with(ui) { }
  17. 17. Anko - Layouts - Demo class SignInActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) } } class SingInView : AnkoComponent<SignInActivity> { override fun createView(ui: AnkoContext<SignInActivity>) = with(ui) { } verticalLayout { } editText { id = R.id.usernameEditText hintResource = R.string.sign_in_username textSize = 24f } editText { id = R.id.passwordEditText hintResource = R.string.signIn_password textSize = 24f } button { id = R.id.signIn_button textResource = R.string.signIn_button } .lparams(width = matchParent, height = wrapContent) .lparams(width = matchParent, height = wrapContent) .lparams(width = matchParent, height = wrapContent) SingInView().setContentView(this)
  18. 18. Anko - Buttons and Toasts With Kotlin we can add click listener and show toast like this: buttonNext.setOnClickListener { Toast.makeText(baseContext, "CLicked!!", Toast.LENGTH_LONG).show; }
  19. 19. Anko - Buttons and Toasts With Kotlin we can add click listener and show toast like this: but with Anko we can do it better: buttonNext.setOnClickListener { Toast.makeText(baseContext, "CLicked!!", Toast.LENGTH_LONG).show; } buttonNext { onClick { toast("Hello ${username.text}") } } or we can show LONG toast: onClick { longToast("Hello ${username.text}") }
  20. 20. Anko - Asynchronous Tasks fun authorizeUser(username: String, password: String) { doAsync { val authorized = signInBL.checkUserCredentials(AuthCredentials(username = username, password = password)) activityUiThread { if (authorized) toast("Signed!!!") else view.showAccessDeniedAlertDialog() } } }
  21. 21. Anko - Asynchronous Tasks Since Anko 0.10-beta1 a new way Anko Coroutines dependencies { compile "org.jetbrains.anko:anko-coroutines:$anko_version" }
  22. 22. Anko - Asynchronous Tasks Since Anko 0.10-beta1 a new way Anko Coroutines suspend fun getData(): Data { ... } class MyActivity : Activity() { fun loadAndShowData() { // Ref<T> uses the WeakReference under the hood val ref: Ref<MyActivity> = this.asReference() async(UI) { val data = getData() // Use ref() instead of this@MyActivity ref().showData() } } fun showData(data: Data) { ... } }
  23. 23. Anko - Asynchronous Tasks Since Anko 0.10-beta1 a new way Anko Coroutines fun getData(): Data { ... } fun showData(data: Data) { ... } async(UI) { val data: Deferred<Data> = bg { // Runs in background getData() } // This code is executed on the UI thread showData(data.await()) } https://github.com/Kotlin/anko/wiki/Anko-Coroutines
  24. 24. Anko - Alerts alert(message = "Hello, I'm Alert Dialog", title = "CZ KUG & eMan") { yesButton { toast("YES pressed!") } noButton { toast("NO pressed!") } }.show()
  25. 25. Anko - Intents Anko contains some useful wrappers for some common intents: // Took it from original Anko documentation // Make a call makeCall(number) // Intent(Intent.ACTION_CALL, Uri.parse("tel:$number")) // startActivity(intent) // Send a text sendSMS(number, [text]) //Browse the web browse(url) //Share some text share(text, [subject]) //Send a email email(email, [subject], [text]) Arguments in square brackets ([]) are optional
  26. 26. Anko - Intents Start a new activity val intent = Intent(this, SomeOtherActivity::class.java) intent.putExtra("id", 5) intent.setFlag(Intent.FLAG_ACTIVITY_SINGLE_TOP) startActivity(intent)
  27. 27. Anko - Intents Start a new activity with Anko: val intent = Intent(this, SomeOtherActivity::class.java) intent.putExtra("id", 5) intent.setFlag(Intent.FLAG_ACTIVITY_SINGLE_TOP) startActivity(intent) startActivity(intentFor<SomeOtherActivity>("id" to 5).singleTop()) startActivity<SomeOtherActivity>("id" to 5)
  28. 28. Anko - Logging class SomeActivity : Activity(), AnkoLogger { private fun someMethod() { info("Prague is the capital of Czech Republic") debug(5) // .toString() method will be executed warn(null) // "null" will be printed } } ….. info { "Prague is the capital of Czech Republic" }
  29. 29. Anko ● Anko SQLite ○ Provides lots of extension functions to simplify working with SQLite dependencies { compile "org.jetbrains.anko:anko-sqlite:$anko_version" } class MySqliteOpenHelper : ManagedSQLiteOpenHelper {} database.use { // Here we have SQL }
  30. 30. Anko ● Anko SQLite ○ Provides lots of extension functions to simplify working with SQLite val values = ContentValues() values.put("id", 1) values.put("name", "Vaclav") values.put("email", "vaclav@email.com") db.insert("User", null, values) db.insert("User", "id" to 1, "name" to "Vaclav", "email" to "vaclav@email.com" )
  31. 31. Anko ● Anko SQLite ○ Provides lots of extension functions to simplify working with SQLite db.select("User", "name") .whereArgs("(_id > {userId}) and (name = {userName})", "userName" to "John", "userId" to 42) https://github.com/Kotlin/anko/wiki/Anko-SQLite
  32. 32. Modern SQL based query & persistance for Java / Kotlin / Android https://github.com/requery/requery
  33. 33. Requery ● Object mapping and SQL generator for Java/Kotlin/Android ○ RxJava and Java 8 support ○ Create databases ○ Perform queries and updates
  34. 34. Requery ● Features ○ No Reflection ○ Typed query language ○ Table generation ○ Supports JDBC and most popular databases (MySQL, Oracle, SQL Server, Postgres and more)
  35. 35. Requery ● Features ○ Compile time entity validation ○ Designed specifically with Android support in mind
  36. 36. Requery ● Using it dependencies { // Requery compile "io.requery:requery:$requeryVersion" compile "io.requery:requery-kotlin:$requeryVersion" compile "io.requery:requery-android:$requeryVersion" // for android }
  37. 37. Requery ● 1. Create Database Source class MyDatabaseSource(context: Context, model: EntityModel, version: Int) : DatabaseSource(context, model, version) { override fun onCreate(db: SQLiteDatabase) override fun onUpgrade(db: SQLiteDatabase?, oldVersion: Int, newVersion: Int) }
  38. 38. Requery ● 2. Kotlin Entity Datastore fun provideDataStore(databaseSource: FiboDatabaseSource): KotlinEntityDataStore<Persistable> { ... }
  39. 39. Requery ● 2. Kotlin Entity Datastore fun provideDataStore(databaseSource: FiboDatabaseSource): KotlinEntityDataStore<Persistable> { if (BuildConfig.DEBUG) { databaseSource.setTableCreationMode(TableCreationMode.DROP_CREATE) } ... }
  40. 40. Requery ● 2. Kotlin Entity Datastore fun provideDataStore(databaseSource: FiboDatabaseSource): KotlinEntityDataStore<Persistable> { if (BuildConfig.DEBUG) { databaseSource.setTableCreationMode(TableCreationMode.DROP_CREATE) } val dataStore = KotlinEntityDataStore<Persistable>(databaseSource.configuration) ... }
  41. 41. Requery ● 2. Kotlin Entity Datastore fun provideDataStore(databaseSource: FiboDatabaseSource): KotlinEntityDataStore<Persistable> { if (BuildConfig.DEBUG) { databaseSource.setTableCreationMode(TableCreationMode.DROP_CREATE) } val dataStore = KotlinEntityDataStore<Persistable>(databaseSource.configuration) databaseSource.dataStore = dataStore return dataStore }
  42. 42. Requery ● Entity interface User : Persistable { }
  43. 43. Requery ● Entity @Entity interface User : Persistable { }
  44. 44. Requery ● Entity @Entity @Table interface User : Persistable { }
  45. 45. Requery ● Entity @Entity @Table(name = “USER”) interface User : Persistable { }
  46. 46. Requery ● Entity @Entity @Table(name = “USER”) interface User : Persistable { var id: Int }
  47. 47. Requery ● Entity @Entity @Table(name = “USER”) interface User : Persistable { @get:Key var id: Int }
  48. 48. Requery ● Entity @Entity @Table(name = “USER”) interface User : Persistable { @get:Key @get:Generated var id: Int }
  49. 49. Requery ● Entity @Entity @Table(name = “USER”) interface User : Persistable { @get:Key @get:Generated var id: Int var userName: String }
  50. 50. Requery ● Entity @Entity @Table(name = “USER”) interface User : Persistable { @get:Key @get:Generated var id: Int @get:Column(length = 20, unique = true, nullable = false) var userName: String }
  51. 51. Requery ● Entity @Entity @Table(name = “USER”) interface User : Persistable { @get:Key @get:Generated var id: Int @get:Column(length = 20, unique = true, nullable = false) var userName: String @get:Column(length = 20, nullable = false) var password: String @get:Column(length = 20) var firstName: String @get:Column(length = 20) var lastName: String @get:Column(length = 30) var email: String }
  52. 52. Requery ● Entity @Entity @Table(name = “USER”) interface User : Persistable { @get:Key @get:Generated var id: Int … val userAccounts: List<UserAccount> }
  53. 53. Requery ● Entity @Entity @Table(name = “USER”) interface User : Persistable { @get:Key @get:Generated var id: Int ... @get:OneToMany val userAccounts: List<UserAccount> }
  54. 54. Requery ● Entity @Entity @Table(name = “USER”) interface User : Persistable { @get:Key @get:Generated var id: Int @get:Column(length = 20, unique = true, nullable = false) var userName: String @get:Column(length = 20, nullable = false) var password: String @get:Column(length = 20) var firstName: String @get:Column(length = 20) var lastName: String @get:Column(length = 30) var email: String @get:OneToMany val userAccounts: List<UserAccount> }
  55. 55. Requery ● Entity @Entity interface UserAccount : Parcelable, Persistable { var user: User var account: Account }
  56. 56. Requery ● Entity @Entity interface UserAccount : Parcelable, Persistable { @get:Key @get:ForeignKey @get:ManyToOne var user: User @get:ForeignKey @get:ManyToOne var account: Account }
  57. 57. Requery override fun existUser(): Boolean { return dataStore.count(UserEntity::class).get().value() > 0 }
  58. 58. Requery override fun findUserById(id: Int): UserDO? { var userDO: UserDO? = null dataStore.invoke { val selectResult = select(UserEntity::class) where (UserEntity.ID.eq(id)) selectResult.get().firstOrNull()?.let { userDO = convertToDO(it) } } return userDO }
  59. 59. Requery override fun insertUser(credentials: AuthCredentials) { val user = UserEntity() with(user) { userName = credentials.userName password = credentials.password } dataStore.insert(user) }
  60. 60. Requery override fun insertUser(credentials: AuthCredentials) { val user = UserEntity() with(user) { userName = credentials.userName password = credentials.password } doAsync { dataStore.insert(user) } }
  61. 61. Requery ● Transaction dataStore { withTransaction { } }
  62. 62. Requery ● Examples
  63. 63. KotlinPref
  64. 64. KotlinPref Android SharedPreferences delegation library for Kotlin object UserInfoPrefModel : KotprefModel() { var userId: Int by intPrefVar(default = -1) var name: String by stringPrefVar() } Live Demo https://github.com/chibatching/Kotpref
  65. 65. PaperParcel
  66. 66. PaperParcel Android Parcelable boilerplate annotation processor
  67. 67. PaperParcel Parcelable class UserDO protected constructor(`in`: Parcel) : Parcelable { private val id: Int private val username: String private val passoword: String ... override fun writeToParcel(dest: Parcel, flags: Int) { dest.writeInt(id) dest.writeString(username) dest.writeString(passoword) } companion object { val CREATOR: Parcelable.Creator<UserDO> = object : Parcelable.Creator<UserDO> { override fun createFromParcel(`in`: Parcel): UserDO { return UserDO(`in`) } override fun newArray(size: Int): Array<UserDO?> { return arrayOfNulls(size) } } } }
  68. 68. PaperParcel @PaperParcel data class UserDO(var id: Int, var username: String, var password: String) : PaperParcelable { companion object { @JvmField val CREATOR = PaperParcelUserDO.CREATOR } } https://github.com/grandstaish/paperparcel
  69. 69. Thanks your for listening! eman.cz

×