Android Jetpack (再)入門 / DevFest Okayama 2019

80a3a3857a55f154d23acb705eff72cc?s=47 star_zero
December 07, 2019

Android Jetpack (再)入門 / DevFest Okayama 2019

80a3a3857a55f154d23acb705eff72cc?s=128

star_zero

December 07, 2019
Tweet

Transcript

  1. Android Jetpack (再)入門 DevFest Okayama 2019 2019/12/07

  2. About me • Kenji Abe • クックパッド株式会社 • Google Developers

    Experts for Android • Twitter: @STAR_ZERO
  3. 話すこと • Android Jetpackの概要 • 各ライブラリの簡単な紹介と使い方 ‣ たくさんあるのでザックリと

  4. Jetpack?

  5. Jetpack? https://developer.android.com/jetpack

  6. Jetpack? • Android開発を加速させてくれるライ ブラリやツールなど • プラットフォームのAPIからは独立さ れてる • 頻繁にアップデートされる •

    必要なものだけを使用可能
  7. Jetpack? https://developer.android.com/jetpack/androidx/versions

  8. Architecture • https://developer.android.com/ jetpack/docs/guide • 推奨しているアーキテクチャのガイド • Jetpackを使うならこれに従うと良い • MVVM

    + Repsitory
  9. Jetpack?

  10. 各ライブラリの 紹介

  11. 使ったほうが良い

  12. 使ったほうが良い • AppCompat • Lifecycles • ViewModel • LiveData

  13. AppCompat • 古いOSとの下位互換 • マテリアルデザインのサポート • 新規プロジェクトでは自動で追加され る • 必ず使いましょう

  14. AppCompat • AppCompatActivity, Fragment • AppCompatButton, AppCompatTextViewなど ‣ レイアウトのButton/TextViewなどは
 自動で変換される

    • その他色々
  15. Lifecycles • Activity/Fragmentのライフサイクル の状態を管理 ‣ LifecycleOwnerを実装してる • ライフサイクルの状態を監視できる • LifecycleOwner使って連携

  16. Lifecycles https://developer.android.com/topic/libraries/architecture/lifecycle

  17. ViewModel • Viewのデータを保持する • 回転などでデータを失わない ‣ Viewなどを保持するとメモリリークす る ‣ OSが破棄したときは対応が必要

  18. ViewModel https://developer.android.com/topic/libraries/architecture/viewmodel

  19. ViewModel class MainViewModel : ViewModel() { // } class MainActivity

    : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) val viewModel = ViewModelProviders .of(this).get(MainViewModel::class.java) } }
  20. LiveData • Observe可能なデータホルダー • Lifecycleのことを知ってる • LifecycleがSTARTED/RESUMEDのと きに変更を通知 • 他のライブラリでも多く使われてる

  21. LiveData class MainViewModel : ViewModel() { private val _data =

    MutableLiveData<String>() val data: LiveData<String> = _data fun fetchData() { val result = // データ取得 _data.value = result } }
  22. LiveData class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?)

    { viewModel.data.observe(this, Observer { // LiveDataが変更されるとココに通知される }) } }
  23. 使っていきたい

  24. 使っていきたい • DataBinding • Navigation

  25. DataBinding • レイアウト(XML)とデータを結合させる • データの変更を自動でUIへ反映 (LiveData) • イベント処理 • XMLに式が書ける

    • XMLからコードを自動生成
  26. DataBinding class MainViewModel : ViewModel() { private val _data =

    MutableLiveData<String>() val data: LiveData<String> = _data fun fetchData() { val result = // データ取得 _data.value = result } }
  27. DataBinding <layout> <data> <variable name="viewModel" type="com...MainViewModel" /> </data> <ConstraintLayout> <TextView

    android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@{viewModel.data}" /> </ConstraintLayout> </layout>
  28. DataBinding class MainActivity : AppCompatActivity() { private lateinit var binding:

    ActivityMainBinding private val viewModel by lazy { } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) binding = DataBindingUtil .setContentView(this, R.layout.activity_main) binding.lifecycleOwner = this binding.viewModel = viewModel } }
  29. DataBinding fun onClickButton() { // ボタンが押されたときの処理 } <Button android:id="@+id/button" android:onClick="@{()

    -> handler.onClickButton()}" />
  30. Navigation • Navigation Editorで画面遷移を定義 ‣ XMLを直接編集も可能 • 主にFragment間の画面遷移 • 引数を型安全に受け渡し可能(SafeArgs)

    • DeepLinkでの遷移
  31. Navigation

  32. Navigation

  33. Navigation <ConstraintLayout> <androidx.fragment.app.FragmentContainerView android:id="@+id/nav_host_fragment" android:name="androidx.navigation.fragment.NavHostFragment" app:defaultNavHost="true" app:navGraph="@navigation/nav_graph" /> </androidx.constraintlayout.widget.ConstraintLayout>

  34. Navigation fun onClickButton() { findNavController() .navigate(R.id.action_mainFragment_to_homeFragment) }

  35. 必要なときに

  36. 必要な時に • WorkManager • Room • Paging • CameraX

  37. WorkManager • バックグラウンドタスクを実行 • ネットワークや充電状況を考慮 • OneTime、定期実行

  38. WorkManager class MyWorker( context: Context, params: WorkerParameters ): Worker(context, params)

    { override fun doWork(): Result { // タスクを実行 return Result.success() } }
  39. WorkManager val constraints = Constraints.Builder() .setRequiredNetworkType(NetworkType.CONNECTED) .setRequiresCharging(true) .build() val workRequest

    = OneTimeWorkRequestBuilder<MyWorker>() .setConstraints(constraints) .build() WorkManager.getInstance(context).enqueue(workRequest)
  40. Room • SQLiteへ簡単にアクセス • @Database, @Entity, @Dao で構成 • リレーションのサポート

    • Android StudioでのSQL構文チェック
  41. Room @Entity data class User( @PrimaryKey val id: Int, @ColumnInfo(name

    = "name") val name: String ) @Dao interface UserDao { @Query("SELECT * FROM user") fun getUsers(): List<User> @Insert fun insert(user: User) }
  42. Room @Database(entities = [User::class], version = 1) abstract class AppDatabase:

    RoomDatabase() { abstract fun userDao(): UserDao }
  43. Room val db = Room.databaseBuilder( requireContext(), AppDatabase::class.java, "my-db" ).build() val

    dao = db.userDao() // データ追加 dao.insert(User(1, "Kenji Abe")) // データ取得 val users = dao.getUsers()
  44. Paging • RecyclerViewのオートページング • Roomは簡単に対応できる • ネットワークアクセスは自分で実装 • クセがあるので難しい

  45. Paging @Dao interface UserDao { @Query("SELECT * FROM user ORDER

    BY id") fun getUsersPaging(): DataSource.Factory<Int, User> } class UserViewMode : ViewModel() { val users = userDao.getUsersPaging().toLiveData(10) }
  46. Paging class UsersAdapter : PagedListAdapter<User, ViewHolder>(DIFF_CALLBACK) { override fun onCreateViewHolder(/*

    */): ViewHolder { // ... return ViewHolder(view) } override fun onBindViewHolder((/* */) { holder.bind(getItem(position)) } }
  47. Paging class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?)

    { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) val adapter = UsersAdapter() recycler.layoutManager = LinearLayoutManager(this) recycler.adapter = adapter viewModel.users.observe(this, Observer { adapter.submitList(it) }) } }
  48. CameraX • カメラアプリの開発を簡単に • デバイス依存コードが不要 • ベンダー拡張機能 ‣ HDR、Portraitなど

  49. CameraX val previewConfig = PreviewConfig.Builder().apply { // ... }.build() val

    preview = Preview(previewConfig) preview.setOnPreviewOutputUpdateListener { // ... } val imageCaptureConfig = ImageCaptureConfig.Builder() .apply { // ... }.build() val imageCapture = ImageCapture(imageCaptureConfig) CameraX.bindToLifecycle(this, preview, imageCapture)
  50. その他いろいろ

  51. その他いろいろ • Benchmark ‣ パフォーマンス測定 • Biometric ‣ 生体認証 •

    ViewPager2 ‣ ViewPagerの新実装(RecyclerView) • Security ‣ 暗号化まわり
  52. KTX

  53. • Kotlinの拡張関数を使って、記述を簡 単に • Coroutinesもサポート • https://developer.android.com/ kotlin/ktx/extensions-list KTX

  54. KTX dependencies { implementation "androidx.core:core-ktx:1.1.0" implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.1.0" implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.1.0" implementation

    "androidx.navigation:navigation-fragment-ktx:2.1.0" implementation "androidx.navigation:navigation-ui-ktx:2.1.0" }
  55. KTX preference.edit() .putBoolean("flag", true) .putInt("value", 1) .apply() // ktxを使った場合 preference.edit

    { putBoolean("flag", true) putInt("value", 1) }
  56. KTX viewModel.data.observe(this, Observer { // ... }) // ktxを使った場合 viewModel.data.observe(this)

    { // ... }
  57. Jetpack Compose

  58. Jetpack Compose • Google I/O 2019で発表 • 宣言的UI ‣ Flutter,

    React, Vue.jsに似てる • Kotlinで書く • まだPreview版 • Android Studio 4.0で試せる
  59. Jetpack Compose

  60. Jetpackを使って Android開発を高速に

  61. ありがとうございました