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

Jetpack最新情報 & Android Architecture Components

Yuki Anzai
December 08, 2018

Jetpack最新情報 & Android Architecture Components

Yuki Anzai

December 08, 2018
Tweet

More Decks by Yuki Anzai

Other Decks in Technology

Transcript

  1. ͋Μ͍͟Ώ͖ • blog : Y.A.M の雑記帳 • y-anz-m.blogspot.com • twitter

    : @yanzm (やんざむ) • uPhyca Inc. (株式会社ウフィカ) • Google Developers Expert for Android
  2. Support Library → AndroidX • Support Library は 28.0.0 で終了

    • package と artifact が AndroidX に変わる • "com.android.support:appcompat-v7:28.0.0" → "androidx.appcompat:appcompat:1.0.0" • 2018/9/21 AndroidX 1.0.0 リリース
  3. How to move • compileSdkVersion 28 以上にする • Support Library

    を 28.0.0 にする • 対応表 : https:// developer.android.com/jetpack/ androidx/migrate • [Refactor] - [Refactor to AndroidX ]
  4. https://developer.android.com/kotlin/ktx 下位互換性、テスト、Kotlin⾔語サポートなど Android KTX Android フレームワークの API や Support Library

    の API をより簡潔に記述できるようにする Kotlin extension function 集 使⽤頻度: Kotlin を使っているなら中〜⾼ "androidx.core:core-ktx:1.0.1" view.viewTreeObserver.addOnPreDrawListener( object : ViewTreeObserver.OnPreDrawListener { override fun onPreDraw(): Boolean { viewTreeObserver.removeOnPreDrawListener(this) actionToBeTriggered() return true } } ) view.doOnPreDraw { actionToBeTriggered() }
  5. https://developer.android.com/training/testing/ 下位互換性、テスト、Kotlin⾔語サポートなど Test Unit テストおよび Instrumentation テストを⾏うための ライブラリとガイダンス 使⽤頻度: ⾼

    androidx.test:core:1.0.0 androidx.test:runner:1.1.0 androidx.test:rules:1.1.0 androidx.test.ext:junit:1.0.0 androidx.test.ext:truth:1.0.0 androidx.test.espresso:espresso-core:3.1.0 …
  6. UI

  7. https://developer.android.com/topic/libraries/data-binding/ Architecture components Data Binding 変更を検知できるデータを UI の要素に宣⾔的に bind する

    ライブラリ 使⽤頻度: 中(使いたければ) <TextView android:text="@{viewmodel.userName}" /> android { ... dataBinding { enabled = true } }
  8. https://developer.android.com/topic/libraries/architecture/lifecycle Architecture components Lifecycles Activity や Fragment のライフサイクルの変化に応じた 処理を簡単に⾏えるようにするライブラリ LiveData

    を使う場合 Lifecycles もほぼ使う 使⽤頻度: ⾼ // Lifecycles only "androidx.lifecycle:lifecycle-runtime:2.0.0" "androidx.lifecycle:lifecycle-compiler:2.0.0"
  9. https://developer.android.com/topic/libraries/architecture/livedata Architecture components LiveData オブザーバーが変更を検知できるデータホルダーを 提供するライブラリ ライフサイクルに応じて、Activity や Fragment が

    active lifecycle state のときだけ通知するということが 可能 使⽤頻度: ⾼ // just LiveData "androidx.lifecycle:lifecycle-viewmodel:2.0.0" "androidx.lifecycle:lifecycle-compiler:2.0.0"
  10. https://developer.android.com/topic/libraries/architecture/viewmodel Architecture components ViewModel Activity の再⽣成を超えてデータを保持するための ライブラリ 使⽤頻度: ⾼ //

    ViewModel and LiveData "androidx.lifecycle:lifecycle-extensions:2.0.0" // just ViewModel "androidx.lifecycle:lifecycle-viewmodel:2.0.0" "androidx.lifecycle:lifecycle-compiler:2.0.0"
  11. 例)Github から google organization のリポジトリ⼀覧を取得して RecyclerView に表⽰する class MainActivity :

    AppCompatActivity() { private val service = createGitHubService(username, token) private val adapter = Adapter() override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) recyclerView.adapter = adapter retryButton.setOnClickListener { load() } load() } private fun load() { progressBar.visibility = View.VISIBLE retryButton.visibility = View.GONE service.reposOf("google").enqueue(object : Callback<List<Repo>> { override fun onResponse(call: Call<List<Repo>>, response: Response<List<Repo>>) { progressBar.visibility = View.GONE if (response.isSuccessful) { adapter.submitList(response.body()!!) } else { retryButton.visibility = View.VISIBLE } } override fun onFailure(call: Call<List<Repo>>, t: Throwable) { progressBar.visibility = View.GONE retryButton.visibility = View.VISIBLE } }) } }
  12. 例)ViewModel & LiveData を使う class MainViewModel : ViewModel() { private

    val service = createGitHubService(username, token) data class Status(val isLoading: Boolean, val data: List<Repo>?, val throwable: Throwable?) private val _status = MutableLiveData<Status>() val status: LiveData<Status> = _status init { load() } fun load() { _status.value = Status(true, null, null) service.reposOf("google").enqueue(object : Callback<List<Repo>> { override fun onResponse(call: Call<List<Repo>>, response: Response<List<Repo>>) { _status.value = if (response.isSuccessful) { Status(false, response.body()!!, null) } else { Status(false, null, IllegalStateException()) } } override fun onFailure(call: Call<List<Repo>>, t: Throwable) { _status.value = Status(false, null, t) } }) } }
  13. 例)ViewModel & LiveData を使う class MainActivity : AppCompatActivity() { private

    val adapter = Adapter() override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) recyclerView.adapter = adapter val viewModel = ViewModelProviders.of(this).get(MainViewModel::class.java) retryButton.setOnClickListener { viewModel.load() } viewModel.status.observe(this, Observer { val (isLoading, data, _) = it if (isLoading) { progressBar.visibility = View.VISIBLE retryButton.visibility = View.GONE } else { progressBar.visibility = View.GONE if (data != null) { adapter.submitList(data) } else { retryButton.visibility = View.VISIBLE } } }) } }
  14. androidx.activity:activity:1.0.0-alpha02 なら class MainActivity : AppCompatActivity() { private val adapter

    = Adapter() private val viewModel: MainViewModel by viewModels() override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) recyclerView.adapter = adapter retryButton.setOnClickListener { viewModel.load() } viewModel.status.observe(this, Observer { when (it) { Status.Loading -> { progressBar.visibility = View.VISIBLE retryButton.visibility = View.GONE } is Status.Success -> { progressBar.visibility = View.GONE adapter.submitList(it.data) } is Status.Error -> { progressBar.visibility = View.GONE retryButton.visibility = View.VISIBLE } } }) } }
  15. 問題点 - Status で data も throwable も両⽅ null というありえない状態を作れてしまう

    data class Status( val isLoading: Boolean, val data: List<Repo>?, val throwable: Throwable? )
  16. 問題点 - Status で data も throwable も両⽅ null というありえない状態を作れてしまう

    → Kotlin の sealed class を使う https://kotlinlang.org/docs/reference/sealed-classes.html sealed class はクラス継承先を制限できる sealed class Expr { data class Const(val number: Double) : Expr() data class Sum(val e1: Expr, val e2: Expr) : Expr() object NotANumber : Expr() } Expr 型のインスタンスの実体は Const, Sum NotANumber のどれか when (expr) { is Expr.Const -> TODO() is Expr.Sum -> TODO() Expr.NotANumber -> TODO() }
  17. 問題点 - Status で data も throwable も両⽅ null というありえない状態を作れてしまう

    sealed class Status<out T> { object Loading : Status<Nothing>() data class Success<T>(val data: T) : Status<T>() data class Error(val throwable: Throwable) : Status<Nothing>() } → Kotlin の sealed class を使う data class Status( val isLoading: Boolean, val data: List<Repo>?, val throwable: Throwable? )
  18. class MainViewModel : ViewModel() { private val service = createGitHubService(username,

    token) private val _status = MutableLiveData<Status<List<Repo>>>() val status: LiveData<Status<List<Repo>>> = _status init { load() } fun load() { _status.value = Status.Loading service.reposOf("google").enqueue(object : Callback<List<Repo>> { override fun onResponse(call: Call<List<Repo>>, response: Response<List<Repo>>) { _status.value = if (response.isSuccessful) { Status.Success(response.body()!!) } else { Status.Error(IllegalStateException()) } } override fun onFailure(call: Call<List<Repo>>, t: Throwable) { _status.value = Status.Error(t) } }) } } 例)ViewModel & LiveData & sealed class を使う
  19. class MainActivity : AppCompatActivity() { private val adapter = Adapter()

    override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) recyclerView.adapter = adapter val viewModel = ViewModelProviders.of(this).get(MainViewModel::class.java) retryButton.setOnClickListener { viewModel.load() } viewModel.status.observe(this, Observer { when (it) { Status.Loading -> { progressBar.visibility = View.VISIBLE retryButton.visibility = View.GONE } is Status.Success -> { progressBar.visibility = View.GONE adapter.submitList(it.data) } is Status.Error -> { progressBar.visibility = View.GONE retryButton.visibility = View.VISIBLE } } }) } } 例)ViewModel & LiveData & sealed class を使う
  20. AndroidX のバージョニング • major version は binary compatibility を指す •

    1.5.0 revision への依存は 1.7.0 に対しても動作するt が、2.0.0 に対しては動かない可能性がある
  21. androidx.activity:activity:1.0.0-alpha02 Activity 最新 : 2018/12/3 Stable なし FragmentActivity, AppCompatActivity のベースクラスとして

    ComponentActivity が 追加された - OnBackPressedCallback を addOnBackPressedCallback() で登録することで onBackPressed() を override せずに intercept できる - ComponentActivity から ViewModel を取得するための by viewModels() Kotlin property delegate - クリックなどの pending input events は onStop() でキャンセルされる - onRetainCustomNonConfigurationInstance は deprecated になり、代わりに ViewModel を利⽤する class MainActivity : AppCompatActivity() { private val viewModel : MainViewModel by viewModels()
  22. androidx.appcompat:appcompat:1.1.0-alpha01 Appcompat 最新 : 2018/12/3 Stable : 2018/11/7 androidx.appcompat:appcompat:1.0.2 1.1.0-alpha01

    - app:drawableLeftCompat, app:drawableRightCompat, app:drawableTopCompat, app:drawableBottomCompat, app:drawableStartCompat, app:drawableEndCompat が追加され、 VectorDrawableCompat を指定可能 <TextView … app:drawableStartCompat="@drawable/ic_info_outline_black_24dp" />
  23. androidx.collection:collection:1.1.0-alpha01 Collection 最新 : 2018/12/3 Stable : 2018/9/21 androidx.collection:collection:1.0.0 1.1.0-alpha01

    - LongSparseArray, SimpleArrayMap, SparseArrayCompat に putIfAbsent() が追加 - SimpleArrayMap に getOrDefault() が追加 - LongSparseArray, SimpleArrayMap, SparseArrayCompat に引数が2つの remove() が追加 - LongSparseArray, SimpleArrayMap, SparseArrayCompat に引数が2つの replace() と引数が3つの replace() が追加 val map = SimpleArrayMap<String, Int>() map.putIfAbsent("Pie", 28) map.remove("Pie", 27) map.replace("Pie", 28) map.replace("Pie", 27, 28)
  24. androidx.core:core:1.1.0-alpha02 Core 最新 : ? Stable : 2018/11/7 androidx.core:core:1.0.1 1.1.0-alpha01

    - NestedScrollingChild3, NestedScrollingParent3 関連 - ShortcutInfoCompat に Persons, categories, isLongLived フィールドが追加された - SupportActivity が ComponentActivity にリネーム - getMainExecutor() メソッドが追加された - Accessibility 関連 - など
  25. androidx.fragment:fragment:1.1.0-alpha02 Fragment 最新 : 2018/12/3 Stable : 2018/9/21 androidx.fragment:fragment:1.0.0 1.1.0-alpha01

    fragment-testing が追加された - テスト⽤の FragmentScenario クラスが追加された(fragment-testing) - FragmentManager に FragmentFactory をセットすることで Fragment インスタン ス⽣成処理をコントロールできる - Fragment から ViewModel を取得するための by viewModels() Kotlin property delegate - クリックなどの pending input events は onStop() でキャンセルされる androidx.fragment:fragment-testing:1.1.0-alpha02 class MainFragment : Fragment() { private val viewModel : MainViewModel by viewModels()
  26. androidx.loader:loader:1.1.0-alpha01 Loader 最新 : 2018/12/3 Stable : 2018/9/21 androidx.loader:loader:1.0.0 1.1.0-alpha01

    - AsyncTaskLoader に getExecutor() が追加 - AsyncTaskLoader のデフォルトの Executor が AsyncTask.THREAD_POOL_EXECUTOR に変更
  27. androidx.media:media:1.1.0-alpha01 Media 最新 : 2018/12/3 Stable : 2018/9/21 androidx.media:media:1.0.0 1.1.0-alpha01

    - MediaSessionCompat の FLAG_HANDLES_MEDIA_BUTTONS と FLAG_HANDLES_TRANSPORT_CONTROLS フラグが deprecated に
  28. androidx.mediarouter:mediarouter:1.1.0-alpha01 MediaRouter 最新 : 2018/12/3 Stable : 2018/9/21 androidx.mediarouter:mediarouter:1.0.0 1.1.0-alpha01

    - dynamic group routes のサポートが追加 - MediaRouteProviders で dynamic group routes をサポートする API が追加 - route 選択とコントロールダイアログに dynamic group routes のための新しい UX が追加
  29. androidx.preference:preference:1.1.0-alpha01 Preference 最新 : 2018/11/5 Stable : 2018/9/21 androidx.preference:preference:1.0.0 1.1.0-alpha01

    - Preference 値が更新されたときに Summary を更新するための SummaryProvider が追加された - ListPreference と EditTextPreference 向けに default の SummaryProvider が⽤意さ れ、app:useSimpleSummaryProvider=”true” で指定できる - PreferenceGroup. removePreferenceRecursively()
  30. androidx.recyclerview:recyclerview:1.1.0-alpha01 RecyclerView 最新 : 2018/12/3 Stable : 2018/9/21 androidx.recyclerview:recyclerview:1.0.0 1.1.0-alpha01

    - RecyclerView が NestedScrollingChild3 を実装 androidx.recyclerview:recyclerview-selection:1.1.0-alpha01 最新 : 2018/12/3 Stable : 2018/9/21 androidx.recyclerview:recyclerview-selection:1.0.0
  31. androidx.remotecallback:remotecallback:1.0.0-alpha01 Remote Callback 最新 : 2018/12/3 Stable なし PendingIntents の⽣成と受信を簡単にすることを⽬的とした新しいライブラリ

    public class MyReceiver : BroadcastReceiverWithCallbacks<MyReceiver>() { fun getPendingIntent(context: Context, value1: Int, value2: Int): PendingIntent { return createRemoteCallback(context) .doMyAction(value1, value2) .toPendingIntent() } @RemoteCallable fun doMyAction(value1: Int, value2: Int): RemoteCallback { // ... return RemoteCallback.LOCAL } }
  32. androidx.swiperefreshlayout:swiperefreshlayout:1.1.0-alpha01 Swipe Refresh Layout 最新 : 2018/12/3 Stable : 2018/9/21

    androidx.swiperefreshlayout:swiperefreshlayout:1.0.0 1.1.0-alpha01 - SwipeRefreshLayout が NestedScrollingChild3 を実装
  33. androidx.vectordrawable:vectordrawable:1.1.0-alpha01 Vector Drawable 最新 : 2018/12/3 Stable : ? androidx.vectordrawable:vectordrawable:1.0.1

    1.1.0-alpha01 - Theme の属性で定義した ColorStateLists を VectorDrawableCompat の tint に利⽤ できるようになった
  34. androidx.versionedparcelable:versionedparcelable:1.1.0-alpha01 Versioned Parcelable 最新 : 2018/11/5 Stable : 2018/9/21 androidx.versionedparcelable:versionedparcelable:1.0.0

    1.1.0-alpha01 - VersionedParcelStream を除く全てのクラスの CharSequence のサポートが追加さ れた - SuperClass, Set, and Map のサポートが追加された
  35. androidx.paging:paging-runtime:2.1.0-rc01 Paging 最新 : 2018/12/6 Stable : 2018/10/1 androidx.paging:paging-runtime:2.0.0 2.1.0-alpha01

    - KTX extension libraries が追加 - Page dropping 機能が追加 - PagedListAdapter/AsyncPagedListDiffer に differ 処理が終わって paged list を更新 するタイミングで通知がくる callback を渡せる submitList() が追加 - など androidx.paging:paging-rxjava2:2.1.0-rc01 androidx.paging:paging-runtime-ktx:2.1.0-rc01 androidx.paging:paging-rxjava2-ktx:2.1.0-rc01 androidx.paging:paging-rxjava2:2.0.0
  36. androidx.room:room-runtime:2.1.0-alpha03 Room 最新 : 2018/12/4 Stable : 2018/10/1 androidx.room:room:2.0.0 2.1.0

    - androidx.room:room-coroutines ライブラリの追加 - FTS(Full Text Search) - VIEWs - Multi-Instance Invalidation - AutoValue - RxRoom
  37. android.arch.work:work-runtime:1.0.0-alpha12 WorkManager 最新 : 2018/12/5 Stable なし 1.0.0-alpha12 - android.arch.work:work-rxjava2

    が追加 - Firebase の JobDispatcher が廃⽌予定のため利⽤されなくなった。将来的に代替⼿ 段が追加される予定 - Worker の output を Result として設定するように変更 - など 1.0.0-alpha11 - android.arch.work:work-runtime-ktx で CoroutineWorker が追加 - など android.arch.work:work-rxjava2:1.0.0-alpha12 android.arch.work:work-runtime-ktx:1.0.0-alpha12
  38. androidx.test:runner:1.1.1-beta01 AndroidJUnitRunner and JUnit Rules 最新 : ? 2018/11/28以降 Stable

    : 2018/10/24 androidx.test:runner:1.1.0 androidx.test:rules:1.1.1-beta01 androidx.test:rules:1.1.0
  39. androidx.test.espresso:espresso-core:3.1.1-beta01 androidx.test.espresso:espresso-contrib:3.1.1-beta01 androidx.test.espresso:espresso-intents:3.1.1-beta01 androidx.test.espresso:espresso-accessibility:3.1.1-beta01 androidx.test.espresso:espresso-web:3.1.1-beta01 Espresso 最新 : ? 2018/11/28移⾏

    Stable : 2018/10/24 androidx.test.espresso:espresso-core:3.1.0 androidx.test.espresso:espresso-contrib:3.1.0 androidx.test.espresso:espresso-intents:3.1.0 androidx.test.espresso:espresso-accessibility:3.1.0 androidx.test.espresso:espresso-web:3.1.0