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

Jetpack最新情報 & Android Architecture Components

Avatar for Yuki Anzai Yuki Anzai
December 08, 2018

Jetpack最新情報 & Android Architecture Components

札幌Android勉強会 sapporo.apk #2
https://sapporo-apk.connpass.com/event/107698/

Avatar for Yuki Anzai

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/guide/topics/ui/noti fi ers/noti fi cations Androidͷඪ४తͳػೳΛ ΞϓϦʹ૊ΈࠐΉͨΊͷ ΨΠμϯε Noti fi

    cations ௨஌Λ࣮૷͢ΔͨΊͷΨΠμϯε ޙํޓ׵ੑͷ͋ΔAPI (Noti fi cationCompat ͳͲ) ͕༻ҙ ͞Ε͍ͯΔ ࢖༻ස౓: ߴ "androidx.core:core:1.0.0"
  8. https://developer.android.com/topic/libraries/data-binding/ Architecture components Data Binding มߋΛݕ஌Ͱ͖ΔσʔλΛ UI ͷཁૉʹએݴతʹ bind ͢Δ

    ϥΠϒϥϦ ࢖༻ස౓: தʢ࢖͍͚ͨΕ͹ʣ <TextView android:text="@{viewmodel.userName}" /> android { ... dataBinding { enabled = true } }
  9. 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"
  10. 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"
  11. 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"
  12. ྫʣ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 } }) }
  13. ྫʣ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) } }) } }
  14. ྫʣ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 } } }) } }
  15. 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 } } }) } }
  16. ໰୊఺ - Status Ͱ data ΋ throwable ΋྆ํ null ͱ͍͏͋Γ͑ͳ͍ঢ়ଶΛ࡞Εͯ͠·͏

    data class Status( val isLoading: Boolean, val data: List<Repo>?, val throwable: Throwable? )
  17. ໰୊఺ - 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() }
  18. ໰୊఺ - 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? )
  19. 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 Λ࢖͏
  20. 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 Λ࢖͏
  21. AndroidX ͷόʔδϣχϯά • major version ͸ binary compatibility Λࢦ͢ •

    1.5.0 revision ΁ͷґଘ͸ 1.7.0 ʹରͯ͠΋ಈ࡞͢Δt ͕ɺ2.0.0 ʹରͯ͠͸ಈ͔ͳ͍Մೳੑ͕͋Δ
  22. 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() ͰΩϟϯηϧ͞ΕΔ - onRetainCustomNonCon fi gurationInstance ͸ deprecated ʹͳΓɺ୅ΘΓʹ ViewModel Λར༻͢Δ class MainActivity : AppCompatActivity() { private val viewModel : MainViewModel by viewModels()
  23. 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" />
  24. 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)
  25. 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 ؔ࿈ - ͳͲ
  26. 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()
  27. 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 ʹมߋ
  28. 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 ʹ
  29. 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 ͕௥Ճ
  30. 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()
  31. 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
  32. 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 } }
  33. 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 Λ࣮૷
  34. 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 ʹར༻Ͱ ͖ΔΑ͏ʹͳͬͨ
  35. 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 ͷαϙʔτ͕௥Ճ͞Εͨ
  36. 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
  37. 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
  38. 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
  39. 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
  40. 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