今からはじめる Android Kotlin

D2bcabeeb1ddff142fb8988b412cb4d3?s=47 Yuki Anzai
August 24, 2019

今からはじめる Android Kotlin

D2bcabeeb1ddff142fb8988b412cb4d3?s=128

Yuki Anzai

August 24, 2019
Tweet

Transcript

  1. 今からはじめる Android Kotlin あんざいゆき(@yanzm) Kotlin Fest 2019

  2. Yuki Anzai • Android App Developer (2009~) • CEO of

    uPhyca Inc. (2011~) • Google Developers Expert for Android • Organizer of GTUG Girls and droid girls • Twitter : @yanzm
  3. Master of Dagger • Dagger 解説本 • 出てくるコードは全部 Kotlin •

    技術書典7 (9⽉22⽇) • TechBooster
  4. Android Kotlin • 2017年の Google I/O で Kotlin が Android

    開発の公式サポート⾔語の1 つになることが発表された
  5. Android Kotlin • 2017年の Google I/O で Kotlin が Android

    開発の公式サポート⾔語の1 つになることが発表された • Professional Android developers の 50% 以上が Kotlin を使っている (Google I/O 2019 より)
  6. Android Kotlin • 2017年の Google I/O で Kotlin が Android

    開発の公式サポート⾔語の1 つになることが発表された • Professional Android developers の 50% 以上が Kotlin を使っている (Google I/O 2019 より) • If you're starting a new project, you should write it in Kotlin; https://android-developers.googleblog.com/2019/05/google-io-2019- empowering-developers-to-build-experiences-on-Android-Play.html
  7. 公式サイト • Kotlin lang • https://kotlinlang.org/docs/tutorials/kotlin-android.html • Android Developers •

    https://developer.android.com/kotlin
  8. None
  9. None
  10. Android プロジェクトで Kotlin を使えるようにする

  11. Kotlin Plugin • Android Studio 3.0 以降は最初から⼊っている

  12. 新規プロジェクトで Kotlin を使う • [File] - [New] - [New Project...]

    Android Studio 3.5
  13. Android Studio 3.5

  14. Android Studio 3.5

  15. None
  16. 既存プロジェクトで Kotlin を使う • Android Studio に設定を追加してもらう⽅法 • ⼿動で設定を追加する⽅法

  17. Android Studio に設定を追加してもらう⽅法 ① • 1. [Tools] - [Kotlin] -

    [Configure Kotlin in Project] • 2. Android with Gradle
  18. • 3. [All modules] または [Single module] を選択して OK をクリックする

    Android Studio に設定を追加してもらう⽅法 ①
  19. Android Studio に設定を追加してもらう⽅法 ② • 1. Kotlin ファイルを追加すると「Kotlin not configured」というメッ

    セージが出るので Configure をクリックする
  20. Android Studio に設定を追加してもらう⽅法 ② • 2. [All modules] または [All

    modules containing Kotlin files] を選択し て OK をクリックする
  21. プロジェクト の build.gradle

  22. モジュール の build.gradle

  23. モジュール の build.gradle を修正する

  24. ⼿動で設定を追加する⽅法 • プロジェクトの build.gradle とモジュールの build.gradle に必要な設定 を追加する

  25. プロジェクトの build.gradle

  26. モジュール の build.gradle 必須 使わないなら不要 必須 使わないなら不要

  27. Android Library モジュールで Kotlin を使う • build.gradle の設定は Android application

    モジュールと同じ • kotlin-android plugin • kotlin-android-extensions plugin (任意) • kotlin-stdlib-jkd7 • core-ktx (任意)
  28. None
  29. None
  30. Library モジュールで Kotlin を使う • Kotlin Library モジュール • New

    Module ウィザードには Java Library しかないので、Java Library を Kotlin Library に変換する
  31. None
  32. モジュール の build.gradle を修正する

  33. Java Library と同じように dependencies に追加できる

  34. Kotlin Style Guide

  35. Kotlin Style Guide • Kotlin lang • https://kotlinlang.org/docs/reference/coding-conventions.html • Android

    Developers • https://developer.android.com/kotlin/style-guide • Kotlin コードに対するの Google’s Android coding standards
  36. None
  37. Code Style • [Preferences] - [Editor] - [Code Style] -

    [Kotlin]
  38. Kotlin style guide に合わせる

  39. ktlint • Kotlin コードのフォーマットに対する linter • チームで PR時にフォーマットのチェックを強制したいときに便利 • https://github.com/pinterest/ktlint

  40. Java コードを Kotlin に 変換する

  41. Java と Kotlin の共存 • Java コードと Kotlin コードはプロジェクトで共存できる •

    テストコードだけ Kotlin にしてみる • 新規のコードは Kotlin で書く • 既存コードを徐々に Kotlin に変えていく
  42. Java と Kotlin の共存 • Java コードと Kotlin コードはプロジェクトで共存できる •

    テストコードだけ Kotlin にしてみる • 新規のコードは Kotlin で書く • 既存コードを徐々に Kotlin に変えていく • 既存の Java コードを Kotlin に変換する作業は Kotlin の学習効率がよい (個⼈の感想です)
  43. Java → Kotlin • 1. [Code] - [Convert Java File

    to Kotlin File] で Kotlin に変換する • 2. 変換後のコードを修正する • !! を ?:, ?.let, lateinit, by などへ書き換える • 標準関数や KTX や Kotlin Android Extensions などを使うようにする
  44. Kotlin ファイルに Java コードをコピペ • Java コードを Kotlin ファイルにコピペすると⾃動で Kotlin

    コードに変 換されて貼り付けられる • 設定で Kotlin に変換させないようにすることもできる
  45. [Preference] - [Editor] - [General] - [Smart Keys] Java コード

    を Kotlin ファイルにペーストしたときに Kotlin に変換するかどうか ペースト時に Kotlin に変換するか確認する ダイアログを出すかどうか
  46. 気をつけること

  47. Convert Java to Kotlin • 愚直な変換 • !!などが残る • !!

    を ?:, ?.let, lateinit, by などへ書き換える • 便利な標準関数などは使われない • Kotlin の標準関数は⼀通りチェックしよう • https://kotlinlang.org/api/latest/jvm/stdlib/index.html
  48. Convert Java to Kotlin • 愚直な変換 • !!などが残る • !!

    を ?:, ?.let, lateinit, by などへ書き換える • 便利な標準関数などは使われない • Kotlin の標準関数は⼀通りチェックしよう • https://kotlinlang.org/api/latest/jvm/stdlib/index.html kotlin.collections kotlin.text パッケージの関数は チェックしよう
  49. Platform type • 昔の Android Framework コードには @NonNull, @Nullable アノテー

    ションがついていない • null が返る可能性に注意しよう
  50. よくある(?)誤解

  51. よくある(?)誤解 • プロジェクトの最初から Kotlin にしないといけない? • → 既存の Java プロジェクトでも

    Kotlin を使うことができる • 全て Kotlin にしないといけない? • → Java コードと Kotlin コードの両⽅をプロジェクトで使えます • Kotlin から既存の Java クラスは使えない? • → 使えます
  52. よくある(?)誤解 • 既存の Java コードから Kotlin のクラスは使えない? • → 使えます

    • Java のライブラリは Kotlin から使えない? • → 使えます
  53. Kotlin Annotation processing tool

  54. Kotlin でアノテーションを使うには • Annotation Processing を使っている Java コードを Kotlin に変換する

    とエラーになった、どうすれば? • Kotlin で書くことになった新規コードで Annotation Processing を利⽤ するライブラリを使いたいがどうすれば?
  55. Kotlin でアノテーションを使うには • Annotation Processing を使っている Java コードを Kotlin に変換する

    とエラーになった、どうすれば? • Kotlin で書くことになった新規コードで Annotation Processing を利⽤ するライブラリを使いたいがどうすれば? kapt を使う https://kotlinlang.org/docs/tutorials/android-frameworks.html
  56. ... apply plugin: 'kotlin-kapt' android { ... } dependencies {

    ... implementation "com.google.dagger:dagger:$dagger_version" kapt "com.google.dagger:dagger-compiler:$dagger_version" } モジュール の build.gradle
  57. Kotlin Android Extensions

  58. Kotlin Android Extensions • Android Studio (IntelliJ IDEA)の Kotlin plugin

    に含まれる機能
  59. ... apply plugin: 'kotlin-android-extensions' android { ... } ... モジュール

    の build.gradle
  60. Kotlin Android Extensions • View binding • Parcelable implementations generator

  61. View binding • レイアウト XML 内の View にアクセスするための Activity の拡張プロパ

    ティを⽣成する
  62. <?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout ...> <TextView android:id="@+id/textView" ... /> </androidx.constraintlayout.widget.ConstraintLayout>

    activity_main.xml
  63. ... class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?)

    { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) findViewById<TextView>(R.id.textView).text = "Hello, world!" } } MainActivity : findViewById 利⽤
  64. ... import kotlinx.android.synthetic.main.activity_main.* class MainActivity : AppCompatActivity() { override fun

    onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) textView.text = "Hello, world!" } } MainActivity
  65. import kotlinx.android.synthetic.main.fragment_main.* class MainFragment : Fragment() { override fun onCreateView(

    inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View? { return inflater.inflate(R.layout.fragment_main, container, false) } override fun onActivityCreated(savedInstanceState: Bundle?) { super.onActivityCreated(savedInstanceState) textView.text = "Hello, world!" } } Fragment
  66. import kotlinx.android.synthetic.main.view_custom.view.* class CustomView : LinearLayout { ... init {

    View.inflate(context, R.layout.view_custom, this) textView.text = "Hello, world!" } } View z
  67. View binding • レイアウト XML 内の View にアクセスするための Activity の拡張プロパ

    ティを⽣成する • Container で View をキャッシュする • Container = Kotlin で書かれた Activity, Fragment, View, LayoutContainer を実装したクラス
  68. public final class MainActivity extends AppCompatActivity { private HashMap _$_findViewCache;

    protected void onCreate(@Nullable Bundle savedInstanceState) { ... } public View _$_findCachedViewById(int var1) { if (this._$_findViewCache == null) { this._$_findViewCache = new HashMap(); } View var2 = (View)this._$_findViewCache.get(var1); if (var2 == null) { var2 = this.findViewById(var1); this._$_findViewCache.put(var1, var2); } return var2; } ... }
  69. View binding • レイアウト XML 内の View にアクセスするための Activity の拡張プロパ

    ティを⽣成する • Container で View をキャッシュする • Container = Kotlin で書かれた Activity, Fragment, View, LayoutContainer を実装したクラス • LayoutContainer (experimental)
  70. experimental 設定 apply plugin: 'kotlin-android-extensions' android { ... } androidExtensions

    { experimental = true } ... モジュール の build.gradle
  71. import kotlinx.android.synthetic.main.list_item.view.* class MyViewHolder(view: View) : RecyclerView.ViewHolder(view) { fun bind(message:

    String) { itemView.textView.text = message } } LayoutContainer なし textView にアクセスできるがキャッシュされない
  72. public final class MyViewHolder extends ViewHolder { public final void

    bind(@NotNull String message) { Intrinsics.checkParameterIsNotNull(message, "message"); View var10000 = this.itemView; Intrinsics.checkExpressionValueIsNotNull(var10000, "itemView"); TextView var2 = (TextView)var10000.findViewById(id.textView); Intrinsics.checkExpressionValueIsNotNull(var2, "itemView.textView"); var2.setText((CharSequence)message); } public MyViewHolder(@NotNull View view) { Intrinsics.checkParameterIsNotNull(view, "view"); super(view); } }
  73. LayoutContainer あり public interface LayoutContainer { /** Returns the root

    holder view. */ public val containerView: View? }
  74. import kotlinx.android.synthetic.main.list_item.* class MyViewHolder( override val containerView: View ) :

    RecyclerView.ViewHolder(containerView), LayoutContainer { fun bind(message: String) { textView.text = message } } LayoutContainer あり キャッシュされる
  75. public final class MyViewHolder extends ViewHolder implements LayoutContainer { @NotNull

    private final View containerView; private HashMap _$_findViewCache; ... public View _$_findCachedViewById(int var1) { if (this._$_findViewCache == null) { this._$_findViewCache = new HashMap(); } View var2 = (View)this._$_findViewCache.get(var1); if (var2 == null) { View var10000 = this.getContainerView(); if (var10000 == null) { return null; } var2 = var10000.findViewById(var1); this._$_findViewCache.put(var1, var2); } return var2; } ... }
  76. Parcelable implementations generator • experimental apply plugin: 'kotlin-android-extensions' android {

    ... } androidExtensions { experimental = true } ...
  77. Parcelable implementations generator • experimental • @Parcelize がついたクラスの Parcelable 実装を⾃動⽣成する

    • primitive types や String, enum , objects などサポートしている型は多 い • サポートしていない型に対しては Custom Parceler で対応できる https://kotlinlang.org/docs/tutorials/android-plugin.html#parcelable-implementations-generator
  78. class User(val name: String, val age: Int) : Parcelable {

    override fun writeToParcel(parcel: Parcel, flags: Int) { parcel.writeString(name) parcel.writeInt(age) } override fun describeContents(): Int = 0 companion object CREATOR : Parcelable.Creator<User> { override fun createFromParcel(parcel: Parcel): User = parcel.run { User(readString()!!, readInt()) } override fun newArray(size: Int): Array<User?> = arrayOfNulls(size) } } ⾃前で実装した場合
  79. @Parcelize class User(val name: String, val age: Int) : Parcelable

    @Parcelize を使った場合
  80. @Parcelize public final class User implements Parcelable { ... public

    static final android.os.Parcelable.Creator CREATOR = new User.Creator(); ... public void writeToParcel(@NotNull Parcel parcel, int flags) { Intrinsics.checkParameterIsNotNull(parcel, "parcel"); parcel.writeString(this.name); parcel.writeInt(this.age); } ... public static class Creator implements android.os.Parcelable.Creator { @NotNull public final Object[] newArray(int size) { return new User[size]; } @NotNull public final Object createFromParcel(@NotNull Parcel in) { Intrinsics.checkParameterIsNotNull(in, "in"); return new User(in.readString(), in.readInt()); } } }
  81. KTX

  82. Android KTX とは • Android Jetpack • Android Framework や

    AndroidX 向けの Kotlin extensions 集 • 拡張関数・拡張プロパティ・ラムダ・名前付き引数・引数のデフォルト値 • core, activity, fragment, viewModel, workManager など様々なライブラ リ向けの ktx がある • https://developer.android.com/kotlin/ktx
  83. core-ktx • Android Framework の API に対する extensions 集 •

    androidx.core:core-ktx:$version sharedPreferences .edit() .putBoolean("key", value) .apply() sharedPreferences.edit { putBoolean("key", value) }
  84. activity-ktx • ComponentActivity に対する extensions 集 • androidx.activity:activity-ktx:$version class MainActivity

    : AppCompatActivity() { private val viewModel: MainViewModel by viewModels() ... }
  85. fragment-ktx • Fragment に対する extensions 集 • androidx.fragment:fragment-ktx:$version class MainFragment

    : Fragment() { private val viewModel: MainViewModel by viewModels() private val viewModel2: MainViewModel by activityViewModels() ... }
  86. livedata-ktx • Android Architecture Components の LiveData に対する extensions 集

    • androidx.lifecycle:lifecycle-livedata-ktx:$version class MainViewModel : ViewModel() { private val _data = MutableLiveData<String>() val data: LiveData<String> get() = _data.distinctUntilChanged() }
  87. viewmodel-ktx • Android Architecture Components の ViewModel に対する extensions 集

    • androidx.lifecycle:lifecycle-viewmodel-ktx:$version class MainViewModel : ViewModel() { fun load() { viewModelScope.launch { ... } } }
  88. KTX との付き合い⽅ • ⼤事なのは KTX の存在を知っていて、必要なときは調べられること • Android のサンプルコード •

    Web 上のコンテンツ • チームのコード
  89. KTX の extensions を調べる • Reference ドキュメントの パッケージ Overview の

    「Extension functions summary」「Extension functions」を⾒る
  90. Android Studio の Kotlin 関係 の機能

  91. Tools - Kotlin

  92. None
  93. Kotlin plugin channel • [Tools] - [Kotlin] - [Configure Kotlin

    Plugin Updates] または [Preferences] - [Languages & Frameworks] - [Kotlin]
  94. Kotlin plugin channel • [Tools] - [Kotlin] - [Configure Kotlin

    Plugin Updates] または [Preferences] - [Languages & Frameworks] - [Kotlin]
  95. Kotlin REPL • [Tools] - [Kotlin] - [Kotlin REPL] •

    対話モードで Kotlin コードを実⾏できる
  96. Show Kotlin Bytecode • [Tools] - [Kotlin] - [Show Kotlin

    Bytecode] • Kotlin Bytecode がみれる
  97. Show Kotlin Bytecode • Decompile ボタンを押すと decompile された Java コードがみれる

  98. その他設定 & 便利機能

  99. Color Scheme • [Preferences] - [Editor] - [Color Scheme] -

    [Kotlin]
  100. Color Scheme • [Preferences] - [Editor] - [Color Scheme] -

    [Kotlin] ⽩系のDefault →
  101. Color Scheme • [Preferences] - [Editor] - [Color Scheme] -

    [Kotlin] 黒系のDarcula →
  102. Inspections • [Preferences] - [Editor] - [Inspections] • [Analyze] -

    [Inspect Code...] でチェックする 項⽬とそのレベル設定
  103. Intentions • [Preferences] - [Editor] - [Intensions]

  104. File and Code Templates • [Preferences] - [Editor] - [File

    and Code Templates] • ファイルとコードのテン プレートをカスタマイズ できる
  105. None
  106. None
  107. None
  108. None
  109. None
  110. None
  111. Postfix Completion • [Preferences] - [Editor] - [General] - [Postfix

    Completion] • キーワードの接尾辞をつけ て tab を押すとコードが補 完される
  112. list.for tab for (i in list) { } 例)for

  113. Live Templates • [Preferences] - [Editor] - [Live Templates] •

    キーワードの略語をタイ プして tab を押すとテン プレートコードが挿⼊さ れる
  114. fun1 tab fun (x: Any): Unit { } 例)fun1

  115. Language Injections • [Preferences] - [Editor] - [Language Injections] •

    ⽂字列を別の⾔語と認識 して編集できる機能
  116. // language=RegExp val pattern = "[a-z]+" ⽅法1) language= @Language("RegExp") val

    pattern = "[a-z]+" ⽅法2) @Language ⽅法3) Kotlin で⾃動認識されるパターン val pattern = "[a-z]+".toRegex() val pattern2 = Regex("[a-z]+")
  117. // language=RegExp val pattern = "[a-z]+" ⽅法1) language= @Language("RegExp") val

    pattern = "[a-z]+" ⽅法2) @Language ⽅法3) Kotlin で⾃動認識されるパターン val pattern = "[a-z]+".toRegex() val pattern2 = Regex("[a-z]+")
  118. まとめ

  119. まとめ • 新規プロジェクトは Kotlin!既存プロジェクトも Kotlin 化を進めたほうが 恩恵を受けられる • Kotlin first

    な Android の取り組みが増えてきている(nullability annotation, KTX, Jetpack Compose) • Java と Kotlin のコードはプロジェクトで共存できる • Kotlin は Java と interoperability があるから安⼼して Kotlin を始めよう
  120. おわり