Slide 1

Slide 1 text

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

Slide 2

Slide 2 text

About me • Kenji Abe • クックパッド株式会社 • Google Developers Experts for Android • Twitter: @STAR_ZERO

Slide 3

Slide 3 text

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

Slide 4

Slide 4 text

Jetpack?

Slide 5

Slide 5 text

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

Slide 6

Slide 6 text

Jetpack? • Android開発を加速させてくれるライ ブラリやツールなど • プラットフォームのAPIからは独立さ れてる • 頻繁にアップデートされる • 必要なものだけを使用可能

Slide 7

Slide 7 text

Jetpack? https://developer.android.com/jetpack/androidx/versions

Slide 8

Slide 8 text

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

Slide 9

Slide 9 text

Jetpack?

Slide 10

Slide 10 text

各ライブラリの 紹介

Slide 11

Slide 11 text

使ったほうが良い

Slide 12

Slide 12 text

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

Slide 13

Slide 13 text

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

Slide 14

Slide 14 text

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

Slide 15

Slide 15 text

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

Slide 16

Slide 16 text

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

Slide 17

Slide 17 text

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

Slide 18

Slide 18 text

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

Slide 19

Slide 19 text

ViewModel class MainViewModel : ViewModel() { // } class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) val viewModel = ViewModelProviders .of(this).get(MainViewModel::class.java) } }

Slide 20

Slide 20 text

LiveData • Observe可能なデータホルダー • Lifecycleのことを知ってる • LifecycleがSTARTED/RESUMEDのと きに変更を通知 • 他のライブラリでも多く使われてる

Slide 21

Slide 21 text

LiveData class MainViewModel : ViewModel() { private val _data = MutableLiveData() val data: LiveData = _data fun fetchData() { val result = // データ取得 _data.value = result } }

Slide 22

Slide 22 text

LiveData class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { viewModel.data.observe(this, Observer { // LiveDataが変更されるとココに通知される }) } }

Slide 23

Slide 23 text

使っていきたい

Slide 24

Slide 24 text

使っていきたい • DataBinding • Navigation

Slide 25

Slide 25 text

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

Slide 26

Slide 26 text

DataBinding class MainViewModel : ViewModel() { private val _data = MutableLiveData() val data: LiveData = _data fun fetchData() { val result = // データ取得 _data.value = result } }

Slide 27

Slide 27 text

DataBinding

Slide 28

Slide 28 text

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 } }

Slide 29

Slide 29 text

DataBinding fun onClickButton() { // ボタンが押されたときの処理 }

Slide 30

Slide 30 text

Navigation • Navigation Editorで画面遷移を定義 ‣ XMLを直接編集も可能 • 主にFragment間の画面遷移 • 引数を型安全に受け渡し可能(SafeArgs) • DeepLinkでの遷移

Slide 31

Slide 31 text

Navigation

Slide 32

Slide 32 text

Navigation

Slide 33

Slide 33 text

Navigation

Slide 34

Slide 34 text

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

Slide 35

Slide 35 text

必要なときに

Slide 36

Slide 36 text

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

Slide 37

Slide 37 text

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

Slide 38

Slide 38 text

WorkManager class MyWorker( context: Context, params: WorkerParameters ): Worker(context, params) { override fun doWork(): Result { // タスクを実行 return Result.success() } }

Slide 39

Slide 39 text

WorkManager val constraints = Constraints.Builder() .setRequiredNetworkType(NetworkType.CONNECTED) .setRequiresCharging(true) .build() val workRequest = OneTimeWorkRequestBuilder() .setConstraints(constraints) .build() WorkManager.getInstance(context).enqueue(workRequest)

Slide 40

Slide 40 text

Room • SQLiteへ簡単にアクセス • @Database, @Entity, @Dao で構成 • リレーションのサポート • Android StudioでのSQL構文チェック

Slide 41

Slide 41 text

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 @Insert fun insert(user: User) }

Slide 42

Slide 42 text

Room @Database(entities = [User::class], version = 1) abstract class AppDatabase: RoomDatabase() { abstract fun userDao(): UserDao }

Slide 43

Slide 43 text

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()

Slide 44

Slide 44 text

Paging • RecyclerViewのオートページング • Roomは簡単に対応できる • ネットワークアクセスは自分で実装 • クセがあるので難しい

Slide 45

Slide 45 text

Paging @Dao interface UserDao { @Query("SELECT * FROM user ORDER BY id") fun getUsersPaging(): DataSource.Factory } class UserViewMode : ViewModel() { val users = userDao.getUsersPaging().toLiveData(10) }

Slide 46

Slide 46 text

Paging class UsersAdapter : PagedListAdapter(DIFF_CALLBACK) { override fun onCreateViewHolder(/* */): ViewHolder { // ... return ViewHolder(view) } override fun onBindViewHolder((/* */) { holder.bind(getItem(position)) } }

Slide 47

Slide 47 text

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) }) } }

Slide 48

Slide 48 text

CameraX • カメラアプリの開発を簡単に • デバイス依存コードが不要 • ベンダー拡張機能 ‣ HDR、Portraitなど

Slide 49

Slide 49 text

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)

Slide 50

Slide 50 text

その他いろいろ

Slide 51

Slide 51 text

その他いろいろ • Benchmark ‣ パフォーマンス測定 • Biometric ‣ 生体認証 • ViewPager2 ‣ ViewPagerの新実装(RecyclerView) • Security ‣ 暗号化まわり

Slide 52

Slide 52 text

KTX

Slide 53

Slide 53 text

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

Slide 54

Slide 54 text

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" }

Slide 55

Slide 55 text

KTX preference.edit() .putBoolean("flag", true) .putInt("value", 1) .apply() // ktxを使った場合 preference.edit { putBoolean("flag", true) putInt("value", 1) }

Slide 56

Slide 56 text

KTX viewModel.data.observe(this, Observer { // ... }) // ktxを使った場合 viewModel.data.observe(this) { // ... }

Slide 57

Slide 57 text

Jetpack Compose

Slide 58

Slide 58 text

Jetpack Compose • Google I/O 2019で発表 • 宣言的UI ‣ Flutter, React, Vue.jsに似てる • Kotlinで書く • まだPreview版 • Android Studio 4.0で試せる

Slide 59

Slide 59 text

Jetpack Compose

Slide 60

Slide 60 text

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

Slide 61

Slide 61 text

ありがとうございました