Upgrade to Pro — share decks privately, control downloads, hide ads and more …

今からはじめる Android Kotlin

Avatar for Yuki Anzai Yuki Anzai
August 24, 2019

今からはじめる Android Kotlin

Avatar for Yuki Anzai

Yuki Anzai

August 24, 2019
Tweet

More Decks by Yuki Anzai

Other Decks in Technology

Transcript

  1. 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
  2. Android Kotlin • 2017年の Google I/O で Kotlin が Android

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

    開発の公式サポート⾔語の1 つになることが発表された • Professional Android developers の 50% 以上が Kotlin を使っている (Google I/O 2019 より)
  4. 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
  5. Android Studio に設定を追加してもらう⽅法 ① • 1. [Tools] - [Kotlin] -

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

    Android Studio に設定を追加してもらう⽅法 ①
  7. Android Studio に設定を追加してもらう⽅法 ② • 2. [All modules] または [All

    modules containing Kotlin files] を選択し て OK をクリックする
  8. Android Library モジュールで Kotlin を使う • build.gradle の設定は Android application

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

    Module ウィザードには Java Library しかないので、Java Library を Kotlin Library に変換する
  10. 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
  11. Java と Kotlin の共存 • Java コードと Kotlin コードはプロジェクトで共存できる •

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

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

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

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

    を Kotlin ファイルにペーストしたときに Kotlin に変換するかどうか ペースト時に Kotlin に変換するか確認する ダイアログを出すかどうか
  16. Convert Java to Kotlin • 愚直な変換 • !!などが残る • !!

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

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

    ションがついていない • null が返る可能性に注意しよう
  19. よくある(?)誤解 • プロジェクトの最初から Kotlin にしないといけない? • → 既存の Java プロジェクトでも

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

    • Java のライブラリは Kotlin から使えない? • → 使えます
  21. Kotlin でアノテーションを使うには • Annotation Processing を使っている Java コードを Kotlin に変換する

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

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

    ... implementation "com.google.dagger:dagger:$dagger_version" kapt "com.google.dagger:dagger-compiler:$dagger_version" } モジュール の build.gradle
  24. ... 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 利⽤
  25. ... 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
  26. 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
  27. 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
  28. View binding • レイアウト XML 内の View にアクセスするための Activity の拡張プロパ

    ティを⽣成する • Container で View をキャッシュする • Container = Kotlin で書かれた Activity, Fragment, View, LayoutContainer を実装したクラス
  29. 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; } ... }
  30. View binding • レイアウト XML 内の View にアクセスするための Activity の拡張プロパ

    ティを⽣成する • Container で View をキャッシュする • Container = Kotlin で書かれた Activity, Fragment, View, LayoutContainer を実装したクラス • LayoutContainer (experimental)
  31. 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 にアクセスできるがキャッシュされない
  32. 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); } }
  33. LayoutContainer あり public interface LayoutContainer { /** Returns the root

    holder view. */ public val containerView: View? }
  34. 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 あり キャッシュされる
  35. 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; } ... }
  36. Parcelable implementations generator • experimental • @Parcelize がついたクラスの Parcelable 実装を⾃動⽣成する

    • primitive types や String, enum , objects などサポートしている型は多 い • サポートしていない型に対しては Custom Parceler で対応できる https://kotlinlang.org/docs/tutorials/android-plugin.html#parcelable-implementations-generator
  37. 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) } } ⾃前で実装した場合
  38. @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()); } } }
  39. KTX

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

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

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

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

    : Fragment() { private val viewModel: MainViewModel by viewModels() private val viewModel2: MainViewModel by activityViewModels() ... }
  44. 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() }
  45. viewmodel-ktx • Android Architecture Components の ViewModel に対する extensions 集

    • androidx.lifecycle:lifecycle-viewmodel-ktx:$version class MainViewModel : ViewModel() { fun load() { viewModelScope.launch { ... } } }
  46. KTX の extensions を調べる • Reference ドキュメントの パッケージ Overview の

    「Extension functions summary」「Extension functions」を⾒る
  47. Kotlin plugin channel • [Tools] - [Kotlin] - [Configure Kotlin

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

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

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

    Bytecode] • Kotlin Bytecode がみれる
  51. Inspections • [Preferences] - [Editor] - [Inspections] • [Analyze] -

    [Inspect Code...] でチェックする 項⽬とそのレベル設定
  52. File and Code Templates • [Preferences] - [Editor] - [File

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

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

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

    ⽂字列を別の⾔語と認識 して編集できる機能
  56. // 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]+")
  57. // 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]+")
  58. まとめ • 新規プロジェクトは Kotlin!既存プロジェクトも Kotlin 化を進めたほうが 恩恵を受けられる • Kotlin first

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