class: chapter-1, hero, center, middle #
Android Jetpack
GDG Shikoku 2018/05/19 荒木佑一 --- class: chapter-1, normal # I/O セッション .card[ .tiny[ - [Android Jetpack: what's new in Android Support Library](https://www.youtube.com/watch?v=jdKUm8tGogw) - [Android Jetpack: what's new in Architecture Components](https://www.youtube.com/watch?v=pErTyQpA390) - [Modern Android development: Android Jetpack, Kotlin, and more](https://www.youtube.com/watch?v=IrMw7MEgADk) - [Android Jetpack: how to smartly use Fragments in your UI](https://www.youtube.com/watch?v=WVPH48lUzGY) - [Android Jetpack: manage UI navigation with Navigation Controller](https://www.youtube.com/watch?v=8GCXtCjtg40) - [Android Jetpack: manage infinite lists with RecyclerView and Paging](https://www.youtube.com/watch?v=BE5bsyGGLf4) - [Android Jetpack: easy background processing with WorkManager](https://www.youtube.com/watch?v=IrKoBFLwTN0) - [Android Slices: build interactive results for Google Search](https://www.youtube.com/watch?v=a7IVH5aNwwc) - [Android Jetpack: sweetening Kotlin development with Android KTX](https://www.youtube.com/watch?v=st1XVfkDWqk) - [Protips: a fresh look at advanced topics for Android experts](https://www.youtube.com/watch?v=eHjHlujp3Tg) - [Android fireside chat](https://www.youtube.com/watch?v=V7E62C9GWFs) ] ] --- class: chapter-2, hero, center, middle # Jetpack --- class: chapter-2, normal # Jetpack とは .card[ ![Jetpack](jetpack.png) Android アプリの開発を助けるリソース アプリ開発者からのフィードバックに基づいて開発 - AndroidX (ライブラリ) * サポート ライブラリ * アーキテクチャー コンポーネント - アプリ開発に関するガイドライン - 開発ツール ] --- class: chapter-2, normal # サポート ライブラリの問題点 .card[ - Maven の名前とパッケージ名が違う
何がどこに入っている? - 命名の失敗
support-v4 の最小 SDK バージョンは 14、名前の -v4 は歴史的事情
パッケージ名にも v4 や v7 が入っているが、無意味 - Android 本体のバージョンにくっついて全部いっしょにリリース
特に関係なくてもリリース、何が変わったか不明瞭 ] --- class: chapter-2, normal # AndroidX .card[ AndroidX: "Android Extension Libraries" - 機能ごとにライブラリを分割
Maven アーティファクト名とパッケージ名が同じ - パッケージ名を整理
v4 とか v7 とかなし - バージョンは [semantic versioning](https://semver.org/lang/ja/) に基づく
1.0.0 にリセット * メジャー: バイナリー互換性 * マイナー: 機能 * パッチ: バグフィックス ] --- class: chapter-2, normal # 例 .card[ androidx.ライブラリ名.パッケージ名.クラス名 android.support.v4.view.ViewCompat
→ androidx.core.view.ViewCompat android.support.v7.app.AppCompatActivity
→ androidx.appcompat.app.AppCompatActivity android.arch.persistence.room.RoomDatabase
→ androidx.room.RoomDatabase ] --- class: chapter-2, normal # 移行手順: 手動 .card[ 書き換え - build.gradle - Java/Kotlin の import - レイアウト XML サポート ライブラリに依存する外部ライブラリ - AndroidX に依存する新しいバージョンがリリースされるまで待つ - Jetifier ] --- class: chapter-2, normal # Jetifier .card[ 外部ライブラリの JAR や AAR を変換 サポートライブラリに依存する JAR / AAR → AndroidX に依存する JAR / AAR 外部ライブラリが更新されるのを待たなくても AndroidX に移行できる ] --- class: chapter-2, normal # 移行手順: 自動 .card[ Refactor to AndroidX .large[ ![Refactor to AndroidX](refactor.png) ] ] --- class: chapter-2, normal # 予定 .card[ - androidx-1.0.0-alpha1 は Android P に依存 (= あくまでプレビュー用) 数ヶ月後 - androidx 1.0.0 正式版 - サポート ライブラリ 28.0.0 アプリ開発者は AndroidX に移行 - androidx 1.1.0 / 2.0.0 ... -
サポート ライブラリ 28.1.0
] --- class: chapter-3, hero, center, middle # 既存ライブラリの新機能 --- class: chapter-3, normal # Lifecycle .card[ ## Fragment#getViewLifecycleOwner() Fragment で ViewModel の中の LiveData を監視して View に表示するときは this ではなく、viewLifecycleOwner を使う ```kotlin override fun onViewCreated(view: View, bundle: Bundle?) { viewModel.liveData.observe(`viewLifecycleOwner`, Observer { // UI を更新 }) } ``` ] --- class: chapter-3, normal # Data Binding .card[ ## LiveData の利用 ちょっと前から ```kotlin class MyFragment : Fragment { val model by viewModel<MyViewModel>() fun onViewCreated(view: View, bundle: Bundle?) { val binding: MyBinding = DataBindingUtil.getBinding(view) `binding.setLifecycleOwner(viewLifecycleOwner)` } } ``` ## インクリメンタル ビルド 速い。もうすぐデフォルトに。 ] --- class: chapter-3, normal # Room .card[ ## Write-Ahead Logging マルチ スレッドで書き込み中でも読み込みできる デフォルト ON ## @RawQuery 検証なしの動的なクエリー ] --- class: chapter-3, normal # RecyclerView .card[ ## ListAdapter リスト項目の増減などをアニメーションするのが簡単に ```kotlin class MyAdapter() : ListAdapter<User, UserViewHolder>(DIFF_CALLBACK) { override fun onBindViewHolder(holder: UserViewHolder, position: Int) { val user: User = getItem(position) // これまで通り } } // Fragment で myAdapter.submitList(list) ``` ] ??? - ListView の ListAdapter とは別 --- class: chapter-4, hero, center, middle # RecyclerView Selection --- class: chapter-4, normal # RecyclerView Selection .card[ タッチ入力による項目選択 - タップで一つ選択 - ドラッグで複数選択 画面回転時に選択内容を保持 ```groovy dependencies { implementation 'androidx.recyclerview:recyclerview-selection:1.0.0-alpha1' } ``` ] --- class: chapter-5, hero, center, middle # androidx.webkit --- class: chapter-5, normal # androidx.webkit .card[ API 21+ WebView の最新機能をバックポート セーフ ブラウジングなど ] --- class: chapter-6, hero, center, middle # HeifWriter --- class: chapter-6, normal # HeifWriter .card[ API P+ (バックポート作業中) HEIF: High Efficiency Image Format
高画質だがファイルサイズが小さい画像フォーマット android.view.Surface や android.graphics.Bitmap を HEIF で保存できる ] --- class: chapter-7, hero, center, middle # Slices --- class: chapter-7, normal # Slices .card[ ![Slices](slices.png) アプリのコンテンツを他のアプリに提供する仕組み - 宣言的な UI ビルダー - インタラクティブな UI - データ更新 API 19+ まずは 検索ボックスの結果から
] --- class: chapter-7, normal # Slice を提供する .card[ AndroidManifest.xml ```xml <provider android.name=".MySliceProvider" android:authority="com.example.slicesample"> </provider> ``` ```kotlin class MySlideProvider : SliceProvider() { override fun onBindSlice(sliceUri: Uri): Slice? { if (uri.path == "/weather") { return ListBuilder(context, sliceUri, ListBuilder.INFINITY) .addRow { it.setTitle("Hello") } .build() } return null } } ``` ] --- class: chapter-8, hero, center, middle # Paging --- class: chapter-8, normal # Paging .card[ RecyclerView に表示するデータ - 多すぎてすべてをメモリに載せたくない - バックエンド API から少しずつ取得したい ページに分割してデータ読み込み ユーザーから見ればシームレスなリスト ] --- class: chapter-8, normal # Room + Paging .card[ ```kotlin @Dao interface UserDao { @Query("SELECT * FROM User") fun allUsersFactory(): DataSource.Factory<Int, User> } ``` ```kotlin val factory: DataSource.Factory = database.allUsersFactory() val users: LiveData<PagedList<User>> = LivePagedListBuilder(factory, 30).build() ``` ] --- class: chapter-8, normal # PagedListAdapter .card[ ```kotlin val adapter: PagedListAdapter<User> = ... users.observe(this) { adapter.submitList(it) } // adapter override fun onBindViewHolder(holder: UserViewHoder, position: Int) { val user: User? = getItem(position) // いつもどおり } ``` ] --- class: chapter-9, hero, center, middle # WorkManager --- class: chapter-9, normal # WorkManager .card[ バックグラウンド処理 アプリが裏に回されても完了してほしい処理 - データのダウンロード・アップロード - 時間のかかる処理 ] --- class: chapter-9, normal # Worker .card[ バックグラウンドで処理したい内容を Worker として実装 ```kotlin class MyWorker : Worker() { override fun doWork(): WorkerResult { // 処理 return WorkerResult.SUCCESS } } ``` ] --- class: chapter-9, normal # Worker を実行 .card[ ```kotlin val work = OneTimeWorkRequestBuilder<MyWorker>() .setConstraints() // ネットワーク、充電中、アイドル状態 .setBackoffCriteria() .setInputData( mapOf("foo" to "Bar").toWorkData() ) .build() WorkManager.getInstance().enqueue(work) ``` ] --- class: chapter-9, normal # バックグラウンド処理使い分け .card[ 画面に表示するものをバックグラウンドで読み込み
→ Executor など 画面に表示しないかもしれないが、バックグラウンドで処理
→ WorkManager バックグラウンドで継続的に処理
→ Foreground Service ] --- class: chapter-10, hero, center, middle # Navigation --- class: chapter-10, normal # Navigation .card[ Activity/Fragment による画面遷移を宣言的に - バックスタック - Up ボタン - 型安全な引数 - ディープ・リンク (ACTION_VIEW) Android Studio 3.2 でサポート ] --- class: chapter-11, hero, center, middle # Fragment について --- class: chapter-11, normal # Fragment .card[ android.app.Fragment は deprecated androidx.fragment.app.Fragment はこれからも発展 Activity = アプリの入り口
Fragment = アプリのコンテンツを表示するもの ] --- class: chapter-11, normal # 昔の Fragment .card[ UI を保持・制御
Activity のライフサイクルを分担
画面遷移 (Fragment Transaction)
データの読み込み・保持 (retainInstance = true)
] --- class: chapter-11, normal # これからの Fragment .card[ UI を保持・制御
Activity のライフサイクルを分担
→ Lifecycle
画面遷移 (Fragment Transaction)
→ Navigation
データの読み込み・保持 (retainInstance = true)
→ ViewModel ] --- class: chapter-12, normal # まとめ .card[ サポート ライブラリ とアーキテクチャー コンポーネントは AndroidX に
プレビュー版で試すことができる - Slices - Paging - WorkManager - Navigation 不具合報告、要望は issuetracker.google.com から ] --- class: chapter-12, hero, middle, center # ありがとうございました