$30 off During Our Annual Pro Sale. View Details »

今からはじめる Android Kotlin

Yuki Anzai
August 24, 2019

今からはじめる Android Kotlin

Yuki Anzai

August 24, 2019
Tweet

More Decks by Yuki Anzai

Other Decks in Technology

Transcript

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

    View Slide

  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

    View Slide

  3. Master of Dagger
    • Dagger 解説本
    • 出てくるコードは全部 Kotlin
    • 技術書典7 (9⽉22⽇)
    • TechBooster

    View Slide

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

    View Slide

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

    View Slide

  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

    View Slide

  7. 公式サイト
    • Kotlin lang
    • https://kotlinlang.org/docs/tutorials/kotlin-android.html
    • Android Developers
    • https://developer.android.com/kotlin

    View Slide

  8. View Slide

  9. View Slide

  10. Android プロジェクトで
    Kotlin を使えるようにする

    View Slide

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

    View Slide

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

    View Slide

  13. Android Studio 3.5

    View Slide

  14. Android Studio 3.5

    View Slide

  15. View Slide

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

    View Slide

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

    View Slide

  18. • 3. [All modules] または [Single module] を選択して OK をクリックする
    Android Studio に設定を追加してもらう⽅法 ①

    View Slide

  19. Android Studio に設定を追加してもらう⽅法 ②
    • 1. Kotlin ファイルを追加すると「Kotlin not configured」というメッ
    セージが出るので Configure をクリックする

    View Slide

  20. Android Studio に設定を追加してもらう⽅法 ②
    • 2. [All modules] または [All modules containing Kotlin files] を選択し
    て OK をクリックする

    View Slide

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

    View Slide

  22. モジュール の build.gradle

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  27. Android Library モジュールで Kotlin を使う
    • build.gradle の設定は Android application モジュールと同じ
    • kotlin-android plugin
    • kotlin-android-extensions plugin (任意)
    • kotlin-stdlib-jkd7
    • core-ktx (任意)

    View Slide

  28. View Slide

  29. View Slide

  30. Library モジュールで Kotlin を使う
    • Kotlin Library モジュール
    • New Module ウィザードには Java Library しかないので、Java Library
    を Kotlin Library に変換する

    View Slide

  31. View Slide

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

    View Slide

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

    View Slide

  34. Kotlin Style Guide

    View Slide

  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

    View Slide

  36. View Slide

  37. Code Style
    • [Preferences] -
    [Editor] - [Code Style]
    - [Kotlin]

    View Slide

  38. Kotlin style guide に合わせる

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  42. Java と Kotlin の共存
    • Java コードと Kotlin コードはプロジェクトで共存できる
    • テストコードだけ Kotlin にしてみる
    • 新規のコードは Kotlin で書く
    • 既存コードを徐々に Kotlin に変えていく
    • 既存の Java コードを Kotlin に変換する作業は Kotlin の学習効率がよい
    (個⼈の感想です)

    View Slide

  43. Java → Kotlin
    • 1. [Code] - [Convert Java File to Kotlin File]
    で Kotlin に変換する
    • 2. 変換後のコードを修正する
    • !! を ?:, ?.let, lateinit, by などへ書き換える
    • 標準関数や KTX や Kotlin Android
    Extensions などを使うようにする

    View Slide

  44. Kotlin ファイルに Java コードをコピペ
    • Java コードを Kotlin ファイルにコピペすると⾃動で Kotlin コードに変
    換されて貼り付けられる
    • 設定で Kotlin に変換させないようにすることもできる

    View Slide

  45. [Preference] - [Editor] - [General] - [Smart Keys]
    Java コード を Kotlin ファイルにペーストしたときに
    Kotlin に変換するかどうか
    ペースト時に Kotlin に変換するか確認する
    ダイアログを出すかどうか

    View Slide

  46. 気をつけること

    View Slide

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

    View Slide

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

    View Slide

  49. Platform type
    • 昔の Android Framework コードには @NonNull, @Nullable アノテー
    ションがついていない
    • null が返る可能性に注意しよう

    View Slide

  50. よくある(?)誤解

    View Slide

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

    View Slide

  52. よくある(?)誤解
    • 既存の Java コードから Kotlin のクラスは使えない?
    • → 使えます
    • Java のライブラリは Kotlin から使えない?
    • → 使えます

    View Slide

  53. Kotlin Annotation
    processing tool

    View Slide

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

    View Slide

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

    View Slide

  56. ...
    apply plugin: 'kotlin-kapt'
    android {
    ...
    }
    dependencies {
    ...
    implementation "com.google.dagger:dagger:$dagger_version"
    kapt "com.google.dagger:dagger-compiler:$dagger_version"
    }
    モジュール の build.gradle

    View Slide

  57. Kotlin Android Extensions

    View Slide

  58. Kotlin Android Extensions
    • Android Studio (IntelliJ IDEA)の Kotlin plugin に含まれる機能

    View Slide

  59. ...
    apply plugin: 'kotlin-android-extensions'
    android {
    ...
    }
    ...
    モジュール の build.gradle

    View Slide

  60. Kotlin Android Extensions
    • View binding
    • Parcelable implementations generator

    View Slide

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

    View Slide



  62. android:id="@+id/textView"
    ... />

    activity_main.xml

    View Slide

  63. ...
    class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)
    findViewById(R.id.textView).text = "Hello, world!"
    }
    }
    MainActivity : findViewById 利⽤

    View Slide

  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

    View Slide

  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

    View Slide

  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

    View Slide

  67. View binding
    • レイアウト XML 内の View にアクセスするための Activity の拡張プロパ
    ティを⽣成する
    • Container で View をキャッシュする
    • Container = Kotlin で書かれた Activity, Fragment, View,
    LayoutContainer を実装したクラス

    View Slide

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

    View Slide

  69. View binding
    • レイアウト XML 内の View にアクセスするための Activity の拡張プロパ
    ティを⽣成する
    • Container で View をキャッシュする
    • Container = Kotlin で書かれた Activity, Fragment, View,
    LayoutContainer を実装したクラス
    • LayoutContainer (experimental)

    View Slide

  70. experimental 設定
    apply plugin: 'kotlin-android-extensions'
    android {
    ...
    }
    androidExtensions {
    experimental = true
    }
    ...
    モジュール の build.gradle

    View Slide

  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 にアクセスできるがキャッシュされない

    View Slide

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

    View Slide

  73. LayoutContainer あり
    public interface LayoutContainer {
    /** Returns the root holder view. */
    public val containerView: View?
    }

    View Slide

  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 あり
    キャッシュされる

    View Slide

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

    View Slide

  76. Parcelable implementations generator
    • experimental
    apply plugin: 'kotlin-android-extensions'
    android {
    ...
    }
    androidExtensions {
    experimental = true
    }
    ...

    View Slide

  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

    View Slide

  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 {
    override fun createFromParcel(parcel: Parcel): User = parcel.run {
    User(readString()!!, readInt())
    }
    override fun newArray(size: Int): Array = arrayOfNulls(size)
    }
    }
    ⾃前で実装した場合

    View Slide

  79. @Parcelize
    class User(val name: String, val age: Int) : Parcelable
    @Parcelize を使った場合

    View Slide

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

    View Slide

  81. KTX

    View Slide

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

    View Slide

  83. core-ktx
    • Android Framework の API に対する extensions 集
    • androidx.core:core-ktx:$version
    sharedPreferences
    .edit()
    .putBoolean("key", value)
    .apply()
    sharedPreferences.edit {
    putBoolean("key", value)
    }

    View Slide

  84. activity-ktx
    • ComponentActivity に対する extensions 集
    • androidx.activity:activity-ktx:$version
    class MainActivity : AppCompatActivity() {
    private val viewModel: MainViewModel by viewModels()
    ...
    }

    View Slide

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

    View Slide

  86. livedata-ktx
    • Android Architecture Components の LiveData に対する extensions

    • androidx.lifecycle:lifecycle-livedata-ktx:$version
    class MainViewModel : ViewModel() {
    private val _data = MutableLiveData()
    val data: LiveData
    get() = _data.distinctUntilChanged()
    }

    View Slide

  87. viewmodel-ktx
    • Android Architecture Components の ViewModel に対する
    extensions 集
    • androidx.lifecycle:lifecycle-viewmodel-ktx:$version
    class MainViewModel : ViewModel() {
    fun load() {
    viewModelScope.launch {
    ...
    }
    }
    }

    View Slide

  88. KTX との付き合い⽅
    • ⼤事なのは KTX の存在を知っていて、必要なときは調べられること
    • Android のサンプルコード
    • Web 上のコンテンツ
    • チームのコード

    View Slide

  89. KTX の extensions を調べる
    • Reference ドキュメントの パッケージ Overview の 「Extension
    functions summary」「Extension functions」を⾒る

    View Slide

  90. Android Studio の Kotlin 関係
    の機能

    View Slide

  91. Tools - Kotlin

    View Slide

  92. View Slide

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

    View Slide

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

    View Slide

  95. Kotlin REPL
    • [Tools] - [Kotlin] - [Kotlin REPL]
    • 対話モードで Kotlin コードを実⾏できる

    View Slide

  96. Show Kotlin Bytecode
    • [Tools] - [Kotlin] - [Show Kotlin Bytecode]
    • Kotlin Bytecode がみれる

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  101. Color Scheme
    • [Preferences] - [Editor] -
    [Color Scheme] - [Kotlin]
    黒系のDarcula →

    View Slide

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

    View Slide

  103. Intentions
    • [Preferences] - [Editor] -
    [Intensions]

    View Slide

  104. File and Code Templates
    • [Preferences] - [Editor] -
    [File and Code
    Templates]
    • ファイルとコードのテン
    プレートをカスタマイズ
    できる

    View Slide

  105. View Slide

  106. View Slide

  107. View Slide

  108. View Slide

  109. View Slide

  110. View Slide

  111. Postfix Completion
    • [Preferences] - [Editor] -
    [General] - [Postfix
    Completion]
    • キーワードの接尾辞をつけ
    て tab を押すとコードが補
    完される

    View Slide

  112. list.for
    tab
    for (i in list) {
    }
    例)for

    View Slide

  113. Live Templates
    • [Preferences] - [Editor]
    - [Live Templates]
    • キーワードの略語をタイ
    プして tab を押すとテン
    プレートコードが挿⼊さ
    れる

    View Slide

  114. fun1
    tab
    fun (x: Any): Unit {
    }
    例)fun1

    View Slide

  115. Language Injections
    • [Preferences] - [Editor]
    - [Language Injections]
    • ⽂字列を別の⾔語と認識
    して編集できる機能

    View Slide

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

    View Slide

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

    View Slide

  118. まとめ

    View Slide

  119. まとめ
    • 新規プロジェクトは Kotlin!既存プロジェクトも Kotlin 化を進めたほうが
    恩恵を受けられる
    • Kotlin first な Android の取り組みが増えてきている(nullability
    annotation, KTX, Jetpack Compose)
    • Java と Kotlin のコードはプロジェクトで共存できる
    • Kotlin は Java と interoperability があるから安⼼して Kotlin を始めよう

    View Slide

  120. おわり

    View Slide