+ - 0:00:00
Notes for current slide
Notes for next slide

Android Jetpack

GDG Shikoku

2018/05/19

荒木佑一

1 / 42

Jetpack

3 / 42

Jetpack とは

Jetpack

Android アプリの開発を助けるリソース

アプリ開発者からのフィードバックに基づいて開発

  • AndroidX (ライブラリ)
    • サポート ライブラリ
    • アーキテクチャー コンポーネント
  • アプリ開発に関するガイドライン
  • 開発ツール
4 / 42

サポート ライブラリの問題点

  • Maven の名前とパッケージ名が違う
    何がどこに入っている?
  • 命名の失敗
    support-v4 の最小 SDK バージョンは 14、名前の -v4 は歴史的事情
    パッケージ名にも v4 や v7 が入っているが、無意味
  • Android 本体のバージョンにくっついて全部いっしょにリリース
    特に関係なくてもリリース、何が変わったか不明瞭
5 / 42

AndroidX

AndroidX: "Android Extension Libraries"

  • 機能ごとにライブラリを分割
    Maven アーティファクト名とパッケージ名が同じ
  • パッケージ名を整理
    v4 とか v7 とかなし
  • バージョンは semantic versioning に基づく
    1.0.0 にリセット
    • メジャー: バイナリー互換性
    • マイナー: 機能
    • パッチ: バグフィックス
6 / 42

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

7 / 42

移行手順: 手動

書き換え

  • build.gradle
  • Java/Kotlin の import
  • レイアウト XML

サポート ライブラリに依存する外部ライブラリ

  • AndroidX に依存する新しいバージョンがリリースされるまで待つ
  • Jetifier
8 / 42

Jetifier

外部ライブラリの JAR や AAR を変換

サポートライブラリに依存する JAR / AAR → AndroidX に依存する JAR / AAR

外部ライブラリが更新されるのを待たなくても AndroidX に移行できる

9 / 42

移行手順: 自動

Refactor to AndroidX

Refactor to AndroidX

10 / 42

予定

  • 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
11 / 42

既存ライブラリの新機能

12 / 42

Lifecycle

Fragment#getViewLifecycleOwner()

Fragment で ViewModel の中の LiveData を監視して View に表示するときは this ではなく、viewLifecycleOwner を使う

override fun onViewCreated(view: View, bundle: Bundle?) {
viewModel.liveData.observe(viewLifecycleOwner, Observer {
// UI を更新
})
}
13 / 42

Data Binding

LiveData の利用

ちょっと前から

class MyFragment : Fragment {
val model by viewModel<MyViewModel>()
fun onViewCreated(view: View, bundle: Bundle?) {
val binding: MyBinding = DataBindingUtil.getBinding(view)
binding.setLifecycleOwner(viewLifecycleOwner)
}
}

インクリメンタル ビルド

速い。もうすぐデフォルトに。

14 / 42

Room

Write-Ahead Logging

マルチ スレッドで書き込み中でも読み込みできる

デフォルト ON

@RawQuery

検証なしの動的なクエリー

15 / 42

RecyclerView

ListAdapter

リスト項目の増減などをアニメーションするのが簡単に

class MyAdapter()
: ListAdapter<User, UserViewHolder>(DIFF_CALLBACK) {
override fun onBindViewHolder(holder: UserViewHolder, position: Int) {
val user: User = getItem(position)
// これまで通り
}
}
// Fragment で
myAdapter.submitList(list)
16 / 42
  • ListView の ListAdapter とは別

RecyclerView Selection

17 / 42

RecyclerView Selection

タッチ入力による項目選択

  • タップで一つ選択
  • ドラッグで複数選択

画面回転時に選択内容を保持

dependencies {
implementation
'androidx.recyclerview:recyclerview-selection:1.0.0-alpha1'
}
18 / 42

androidx.webkit

19 / 42

androidx.webkit

API 21+

WebView の最新機能をバックポート

セーフ ブラウジングなど

20 / 42

HeifWriter

21 / 42

HeifWriter

API P+ (バックポート作業中)

HEIF: High Efficiency Image Format
高画質だがファイルサイズが小さい画像フォーマット

android.view.Surface や android.graphics.Bitmap を HEIF で保存できる

22 / 42

Slices

23 / 42

Slices

Slices

アプリのコンテンツを他のアプリに提供する仕組み

  • 宣言的な UI ビルダー
  • インタラクティブな UI
  • データ更新

API 19+

まずは 検索ボックスの結果から



24 / 42

Slice を提供する

AndroidManifest.xml

<provider android.name=".MySliceProvider"
android:authority="com.example.slicesample">
</provider>
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
}
}
25 / 42

Paging

26 / 42

Paging

RecyclerView に表示するデータ

  • 多すぎてすべてをメモリに載せたくない
  • バックエンド API から少しずつ取得したい

ページに分割してデータ読み込み

ユーザーから見ればシームレスなリスト

27 / 42

Room + Paging

@Dao
interface UserDao {
@Query("SELECT * FROM User")
fun allUsersFactory(): DataSource.Factory<Int, User>
}
val factory: DataSource.Factory = database.allUsersFactory()
val users: LiveData<PagedList<User>>
= LivePagedListBuilder(factory, 30).build()
28 / 42

PagedListAdapter

val adapter: PagedListAdapter<User> = ...
users.observe(this) {
adapter.submitList(it)
}
// adapter
override fun onBindViewHolder(holder: UserViewHoder, position: Int) {
val user: User? = getItem(position)
// いつもどおり
}
29 / 42

WorkManager

30 / 42

WorkManager

バックグラウンド処理

アプリが裏に回されても完了してほしい処理

  • データのダウンロード・アップロード
  • 時間のかかる処理
31 / 42

Worker

バックグラウンドで処理したい内容を Worker として実装

class MyWorker : Worker() {
override fun doWork(): WorkerResult {
// 処理
return WorkerResult.SUCCESS
}
}
32 / 42

Worker を実行

val work = OneTimeWorkRequestBuilder<MyWorker>()
.setConstraints() // ネットワーク、充電中、アイドル状態
.setBackoffCriteria()
.setInputData(
mapOf("foo" to "Bar").toWorkData()
)
.build()
WorkManager.getInstance().enqueue(work)
33 / 42

バックグラウンド処理使い分け

画面に表示するものをバックグラウンドで読み込み
→ Executor など

画面に表示しないかもしれないが、バックグラウンドで処理
→ WorkManager

バックグラウンドで継続的に処理
→ Foreground Service

34 / 42

Navigation

35 / 42

Navigation

Activity/Fragment による画面遷移を宣言的に

  • バックスタック
  • Up ボタン
  • 型安全な引数
  • ディープ・リンク (ACTION_VIEW)

Android Studio 3.2 でサポート

36 / 42

Fragment について

37 / 42

Fragment

android.app.Fragment は deprecated

androidx.fragment.app.Fragment はこれからも発展

Activity = アプリの入り口
Fragment = アプリのコンテンツを表示するもの

38 / 42

昔の Fragment

UI を保持・制御

Activity のライフサイクルを分担
 

画面遷移 (Fragment Transaction)
 

データの読み込み・保持 (retainInstance = true)
 

39 / 42

これからの Fragment

UI を保持・制御

Activity のライフサイクルを分担
→ Lifecycle

画面遷移 (Fragment Transaction)
→ Navigation

データの読み込み・保持 (retainInstance = true)
→ ViewModel

40 / 42

まとめ

サポート ライブラリ とアーキテクチャー コンポーネントは AndroidX に
プレビュー版で試すことができる

  • Slices
  • Paging
  • WorkManager
  • Navigation

不具合報告、要望は issuetracker.google.com から

41 / 42

ありがとうございました

42 / 42
Paused

Help

Keyboard shortcuts

, , Pg Up, k Go to previous slide
, , Pg Dn, Space, j Go to next slide
Home Go to first slide
End Go to last slide
Number + Return Go to specific slide
b / m / f Toggle blackout / mirrored / fullscreen mode
c Clone slideshow
p Toggle presenter mode
t Restart the presentation timer
?, h Toggle this help
Esc Back to slideshow