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

Androidアプリ開発研修【MIXI 23新卒技術研修】

Androidアプリ開発研修【MIXI 23新卒技術研修】

23新卒技術研修で実施したAndroidアプリ開発研修の講義資料です。

動画:https://youtu.be/VfZMuEL2tGk

ハンズオン用リポジトリ:https://github.com/mixigroup/2023AndroidTraining

資料の利用について
公開している資料は勉強会や企業の研修などで自由にご利用頂いて大丈夫ですが、以下の形での利用だけご遠慮ください。
・受講者から参加費や授業料などを集める形での利用(会場費や飲食費など勉強会運営に必要な実費を集めるのは問題ありません)
・出典を削除または改変しての利用

MIXI ENGINEERS
PRO

April 26, 2023
Tweet

More Decks by MIXI ENGINEERS

Other Decks in Technology

Transcript

  1. Android
    2023.4.26
    Android Google LLC

    View Slide

  2. ©MIXI
    2
    2017
    Vantage KARASTA
    2015
    Vantage M

    View Slide

  3. View Slide

  4. ©MIXI
    4
    Android
    Android

    View Slide

  5. View Slide

  6. ©MIXI
    6
    1 Android
    2
    3 UI
    4
    5
    6
    7
    8
    9
    10

    View Slide

  7. Android
    1

    View Slide

  8. ©MIXI
    Android
    8
    Android Auto
    Android TV
    PC
    ChromeOS
    Wear OS
    ,

    View Slide

  9. ©MIXI
    Android
    9
    API
    (SDK )
    2008.09 1.0 1 Base
    ...
    2017.08 8.0 26 Oreo
    2017.12 8.1 27 Oreo MR1
    2018.08 9 28 Pie
    2019.09 10 29 Q
    2020.09 11 30 R
    2021.10 12 31 S
    2022.03 12L 32 S v2
    2022.08 13 33 Tiramisu
    - 14 34 Upside Down Cake
    API
    ( )

    View Slide

  10. ©MIXI
    Android Studio
    IntelliJ IDEA ⾒
    https://developer.android.com/studio
    10

    View Slide

  11. ©MIXI
    11
    Android Studio
    APK
    (Android Application Package)
    AVD (Android Virtual Device)

    View Slide

  12. ©MIXI
    12
    Android Studio
    AAB
    (Android App Bundle)
    Google Play

    View Slide

  13. ©MIXI
    13
    Android Studio
    AAB
    (Android App Bundle)
    Google Play
    :
    : xxhdpi
    CPU: arm
    :
    : hdpi
    CPU: x86
    APK

    View Slide

  14. ©MIXI
    14
    Android Studio
    AAB
    (Android App Bundle)
    Google Play
    l
    l
    :
    : xxhdpi
    CPU: arm
    :
    : hdpi
    CPU: x86

    View Slide

  15. ©MIXI
    Kotlin
    Android (2017 )
    Java
    15
    Kotlin
    l :
    l Null :
    l Java : Kotlin Java Java Kotlin

    View Slide

  16. ©MIXI
    Kotlin
    Android (2017 )
    Java
    16
    Kotlin
    l :
    l Null :
    l Java : Kotlin Java Java Kotlin
    NullPointerException
    var count: Int // null
    var count: Int? // null

    View Slide

  17. ©MIXI
    Kotlin
    Android, iOS, Web
    https://kotlinlang.org/docs/multiplatform.html
    17
    Kotlin Multiplatform
    Kotlin UI ( )
    https://developer.android.com/jetpack/compose?hl=ja
    Jetpack Compose

    View Slide

  18. ©MIXI
    Wear OS, ChromeOS, Android TV, Android Auto
    API
    : Android 13 API 33, Tiramisu
    APK :
    AAB : Google Play APK
    : , Null , Java
    Kotlin : Kotlin Multiplatform, Jetpack Compose
    18
    Android
    Kotlin

    View Slide

  19. 2

    View Slide

  20. ©MIXI
    Android Studio New Project
    20

    View Slide

  21. ©MIXI
    Empty Activity (Activity )
    Jetpack Compose
    21

    View Slide

  22. ©MIXI
    Name
    Package name
    ID
    { }.{ }
    : jp.co.mixi.karasta
    Minimum SDK
    22

    View Slide

  23. ©MIXI
    AVD ( ) ⾒
    https://developer.android.com/studio/run/managing-avds?hl=ja
    23
    AVD

    View Slide

  24. ©MIXI
    24
    , ,
    Kotlin
    ,

    View Slide

  25. ©MIXI
    ( )
    1.
    https://developer.android.com/studio/debug/dev-options?hl=ja#enable
    2. USB ON
    3. USB Android Studio
    25
    1. USB

    View Slide

  26. ©MIXI
    ( )
    1. Android 11 PC
    2.
    https://developer.android.com/studio/debug/dev-options?hl=ja#enable
    3. Android Studio Pair Devices Using Wi-Fi
    4. ON
    5. Android Studio
    6. Android Studio
    26
    2. Wi-Fi

    View Slide

  27. UI
    3

    View Slide

  28. ©MIXI
    :
    1. Android Studio Get from VCS
    28
    2. URL [email protected]:mixigroup/2023AndroidTraining.git
    git clone OK
    3. app.ui
    1

    View Slide

  29. ©MIXI
    Jetpack
    l
    l
    29
    app
    Android 13 Android 12 Android 11
    if else if else ...
    app
    Android 13 Android 12 Android 11
    Jetpack

    View Slide

  30. ©MIXI
    Jetpack Compose
    Jetpack
    Kotlin UI
    2021
    UI ( )
    https://developer.android.com/jetpack/compose?hl=ja
    30

    View Slide

  31. ©MIXI
    31
    View : UI Compose : UI
    val textView = TextView(context)
    textView.setText("Hello")
    textView.setTextColor(Color.BLUE)
    Text(
    text = "Hello",
    color = Color.Blue
    )
    View
    UI
    View
    Composable
    UI Composable

    View Slide

  32. ©MIXI
    32
    View : UI Compose : UI
    val textView = TextView(context)
    textView.setText("Hello")
    textView.setTextColor(Color.BLUE)
    Text(
    text = "Hello",
    color = Color.Blue
    )
    Composable
    UI Composable
    UI
    Recompose

    View Slide

  33. ©MIXI
    Composable
    33
    @Composable
    fun RedText(
    text: String,
    modifier: Modifier = Modifier
    ) {
    Text(
    text = text,
    modifier = modifier,
    color = Color.Red
    )
    }
    RedText(
    text = "Red text"
    )
    RedText(
    text = "Red text with blue background",
    modifier = Modifier.background(Color.Blue)
    )

    View Slide

  34. ©MIXI
    Composable
    34
    @Composable
    fun RedText(
    text: String,
    modifier: Modifier = Modifier
    ) {
    Text(
    text = text,
    modifier = modifier,
    color = Color.Red
    )
    }
    Composable
    Compose
    Composable
    l ProfileScreen
    l LoginButton
    l HeaderImage

    View Slide

  35. ©MIXI
    Composable
    35
    // modifier
    RedText(
    text = "Red text"
    )
    // modifier
    RedText(
    text = "Red text with blue background",
    modifier = Modifier.background(Color.Blue)
    )
    text =
    modifier
    API

    View Slide

  36. ©MIXI
    Composable
    Composable
    Composable Composable
    API ( )
    36
    Button {
    Text(text = "Hello")
    }
    Composable

    View Slide

  37. ©MIXI
    Composable
    37
    @Composable
    fun Button(
    ...
    content: @Composable () -> Unit
    )
    Button(content = { Text(text = "Hello") })
    Button() { Text(text = "Hello") }
    Button { Text(text = "Hello") }
    ( ) ->
    () -> Unit
    { -> }
    ()
    ()

    View Slide

  38. ©MIXI
    Modifier.padding(all = 8.dp)
    Modifier.padding(horizontal = 8.dp, vertical = 4.dp)
    Modifier.padding(start = 8.dp, top = 4.dp, end = 8.dp, bottom = 16.dp)
    Modifier
    38
    // 96 x 48 dp
    Modifier.width(96.dp).height(48.dp)
    // 48 x 48 dp
    Modifier.size(48.dp)
    //
    Modifier.fillMaxWidth().wrapContentHeight()
    //
    Modifier.fillMaxSize()
    dp

    View Slide

  39. ©MIXI
    DP
    Px
    39
    DP : density-independent pixels
    : :
    : :

    View Slide

  40. ©MIXI
    40
    SP : scalable pixels

    View Slide

  41. ©MIXI
    Button, Checkbox, TopAppBar Composable
    41
    API
    https://developer.android.com/reference/kotlin/androidx/compose/material3/package-summary
    https://m3.material.io/components

    View Slide

  42. ©MIXI
    Composable Composable
    42
    Column Row

    View Slide

  43. ©MIXI
    Composable
    43
    Column(
    horizontalAlignment = Alignment.CenterHorizontally,
    verticalArrangement = Arrangement.spacedBy(8.dp)
    ) {
    Text(text = "Top")
    Text(text = "Center")
    Text(text = "Bottom")
    }
    Composable (36 )

    View Slide

  44. ©MIXI
    Composable
    Spacer
    44
    Column(horizontalAlignment = Alignment.CenterHorizontally) {
    Text(text = "Top")
    Spacer(modifier = Modifier.height(8.dp))
    Text(text = "Center")
    Spacer(modifier = Modifier.height(8.dp))
    Text(text = "Bottom")
    }

    View Slide

  45. ©MIXI
    45
    Column(modifier = modifier.height(160.dp)) {
    Text(text = "Top", modifier = Modifier.weight(1f))
    Text(text = "Center")
    Text(text = "Bottom")
    }
    Column(modifier = modifier.height(160.dp)) {
    Text(text = "Top", modifier = Modifier.weight(1f))
    Text(text = "Center", modifier = Modifier.weight(2f))
    Text(text = "Bottom", modifier = Modifier.weight(3f))
    }
    1:2:3 ⾒

    View Slide

  46. ©MIXI
    Composable
    46
    Row(
    horizontalArrangement = Arrangement.spacedBy(8.dp),
    verticalAlignment = Alignment.CenterVertically
    ) {
    Text(text = "Left")
    Text(text = "Center")
    Text(text = "Right")
    }
    Row : Column

    View Slide

  47. ©MIXI
    : LazyColumn
    Compose
    47
    Column LazyColumn
    Compose
    Item 1
    Item 2
    Item 3
    Item 4
    Item 5
    Item 6
    Item 7
    Item 8
    Item 1
    Item 2
    Item 3
    Item 4
    Item 5
    Item 6
    Item 7
    Item 8
    Compose

    View Slide

  48. ©MIXI
    LazyColumn
    LazyRow
    48
    LazyColumn(
    horizontalAlignment = Alignment.CenterHorizontally,
    verticalArrangement = Arrangement.spacedBy(8.dp)
    ) {
    // 1
    item {
    Text(text = "Header")
    }
    //
    items(listOf("1", "2", "3")) { text ->
    Text(text = text)
    }
    }

    View Slide

  49. ©MIXI
    Composable
    @Preview 築
    49

    View Slide

  50. ©MIXI
    3.1
    app.ui BookItem
    Android Studio Tips
    50
    16 dp
    8 dp
    8 dp
    4 dp
    18 sp,
    16 sp
    16 dp
    title
    author

    View Slide

  51. ©MIXI
    Android Studio Tips
    Option + Enter import
    51
    Unresolved reference
    Command + B
    Command +

    View Slide

  52. ©MIXI
    3.2 ( )
    API
    https://developer.android.com/reference/kotlin/androidx/compose/material3/package-summary
    52

    View Slide

  53. ©MIXI
    UI
    53
    Jetpack
    UI Kotlin
    Jetpack Compose
    Composable
    UI
    Modifier
    Composable
    Column , Row , LazyColumn / LazyRow
    DP , SP

    View Slide

  54. 4

    View Slide

  55. ©MIXI
    Android
    55
    ( )
    l String resource
    l Drawable resource
    l Raw resource
    src/main/res/

    View Slide

  56. ©MIXI
    res/values/strings.xml
    56



    ...

    Text(text = stringResource(id = R.string.login))
    Text(text = stringResource(id = R.string.settings))
    UI

    View Slide

  57. ©MIXI
    57
    strings.xml
    strings.xml
    1 2

    View Slide

  58. ©MIXI
    58
    strings.xml
    Settings
    res/values/strings.xml res/values-ja/strings.xml

    View Slide

  59. ©MIXI
    59
    : JPG, PNG, WebP
    : SVG

    View Slide

  60. ©MIXI
    60
    res/drawable-mdpi/
    res/drawable-hdpi/
    res/drawable-xhdpi/
    res/drawable-xxhdpi/
    res/drawable-xxxhdpi/
    res/drawable/
    Adobe XD Sketch
    Android Studio VectorDrawable
    ( )

    View Slide

  61. ©MIXI
    VectorDrawable
    61
    SVG
    or

    View Slide

  62. ©MIXI
    Icon(
    painter = painterResource(id = R.drawable.ramen),
    contentDescription = stringResource(R.string.ramen),
    tint = Color.Red
    )
    62
    Image(
    painter = painterResource(id = R.drawable.ramen),
    contentDescription = stringResource(R.string.ramen)
    )
    Icon

    View Slide

  63. ©MIXI
    Modifier
    63
    Image(
    ...
    modifier = Modifier.clip(CircleShape)
    )
    Image(
    ...
    modifier = Modifier.clip(RoundedCornerShape(size = 8.dp))
    )

    View Slide

  64. ©MIXI
    4.1
    3.1 BookItem
    3.1 ⾒ answer/3.1

    View Slide

  65. ©MIXI
    8dp padding
    4.2
    BookItem
    65
    16 dp 16 dp
    48 x 48 dp
    l Android Studio
    l Modifier (33 )
    l Modifier : https://developer.android.com/jetpack/compose/modifiers?hl=ja#order-modifier-matters

    View Slide

  66. ©MIXI
    4.3 ( )
    4.1
    https://developer.android.com/training/basics/supporting-devices/languages?hl=ja
    66
    l
    l

    View Slide

  67. ©MIXI
    67
    res/values/strings.xml
    l
    l
    Android Studio VectorDrawable

    View Slide

  68. 5

    View Slide

  69. ©MIXI
    Text(text = " ")
    Composable
    (Recompose) UI
    69
    Text(text = " ")

    View Slide

  70. ©MIXI
    70
    0
    1
    1 2

    View Slide

  71. ©MIXI
    1 :
    71
    var count = 0
    Button(onClick = {
    count++
    }) {
    Text(text = count.toString())
    }
    count Recompose
    val :
    var :
    0
    0

    View Slide

  72. ©MIXI
    1 :
    72
    var count by remember { mutableStateOf(0) }
    Button(onClick = {
    count++
    }) {
    Text(text = count.toString())
    }
    MutableState
    Compose
    Recompose
    (UI
    )

    View Slide

  73. ©MIXI
    1 :
    73
    var count by remember { mutableStateOf(0) }
    Button(onClick = {
    count++
    }) {
    Text(text = count.toString())
    }
    Delegated property
    MutableState
    Int
    remember
    Recompose
    API
    : https://developer.android.com/jetpack/compose/state#state-in-composables

    View Slide

  74. ©MIXI
    1 :
    74
    var count by remember { mutableStateOf(0) }
    Button(onClick = {
    count++
    }) {
    Text(text = count.toString())
    }
    0
    1

    View Slide

  75. ©MIXI
    var text by remember { mutableStateOf("") }
    TextField(
    value = text,
    onValueChange = { value ->
    text = value
    }
    )
    2 :
    75

    View Slide

  76. ©MIXI
    5.1
    app.login LoginScreen
    l
    l ID 4 8
    ( )
    76

    View Slide

  77. ©MIXI
    5.2 ( )
    UI
    https://developer.android.com/reference/kotlin/androidx/compose/material3/package-summary
    77
    l Switch
    l Checkbox
    l Slider

    View Slide

  78. ©MIXI
    78
    Composable (Recompose) UI
    MutableState Recompose
    var state by remember { mutableStateOf( ) }
    UI
    Composable onClick onValueChange
    e.g. Button, TextField, Switch
    UI
    UI

    View Slide

  79. 6

    View Slide

  80. ©MIXI
    80

    View Slide

  81. ©MIXI
    81

    View Slide

  82. ©MIXI
    82
    1
    2
    3

    View Slide

  83. ©MIXI
    83
    :

    View Slide

  84. ©MIXI
    84
    Log.v(TAG, " ")
    Log.d(TAG, " ")
    Log.i(TAG, " ")
    Log.w(TAG, " ")
    Log.e(TAG, " ")
    ( )

    View Slide

  85. ©MIXI
    package:mine
    85
    package:
    tag:
    Log
    level:

    View Slide

  86. ©MIXI
    86
    l
    l
    l
    l

    View Slide

  87. 7

    View Slide

  88. ©MIXI
    ( )
    88
    A B
    A B
    l
    l
    UI
    l

    View Slide

  89. ©MIXI
    https://developer.android.com/topic/architecture?hl=ja
    89
    UI
    l UI
    l
    l UI
    l
    l UI
    l ( )

    View Slide

  90. ©MIXI
    UI
    90
    UI
    UI
    Compose
    l UI
    l UI
    ViewModel
    l UI
    l UI
    UI

    View Slide

  91. ©MIXI
    91
    UI
    UI
    ( )

    View Slide

  92. ©MIXI
    UI
    92
    Jetpack Room
    SQLite
    Jetpack DataStore
    Key-Value
    Retrofit
    HTTP
    Ktor
    Kotlin Kotlin
    HTTP

    View Slide

  93. ©MIXI
    : ver.
    93
    Column(...) {
    var result by remember { mutableStateOf("") }
    Text(text = result)
    Button(onClick = {
    result = listOf(" ", " ", ...).random()
    }) {
    Text(text = stringResource(R.string.pick_omikuji))
    }
    }

    View Slide

  94. ©MIXI
    94
    UI
    l
    l ( )
    l UI
    l

    View Slide

  95. ©MIXI
    ( )
    95
    class OmikujiRepository {
    fun getResult(): String {
    return listOf(" 規", "規", ...).random()
    }
    }

    View Slide

  96. ©MIXI
    UI
    96
    data class OmikujiUiState(
    val result: String = ""
    )
    equals() copy()
    OK

    View Slide

  97. ©MIXI
    Jetpack
    97
    class OmikujiViewModel() : ViewModel() {
    ...
    }
    UI
    ViewModel
    ViewModel

    View Slide

  98. ©MIXI
    ViewModel
    98
    class OmikujiViewModel(
    private val repository: OmikujiRepository = OmikujiRepository()
    ) : ViewModel() {
    ...
    }
    (DI)
    Hilt DI

    View Slide

  99. ©MIXI
    UiState MutableState
    99
    class OmikujiViewModel(...) : ViewModel() {
    var uiState by mutableStateOf(OmikujiUiState())
    private set
    }
    MutableStateFlow
    l MutableState Compose API
    l MutableStateFlow Kotlin API

    View Slide

  100. ©MIXI
    UiState ViewModel
    100
    class OmikujiViewModel(...) : ViewModel() {
    ...
    fun pick() {
    val result = repository.getResult()
    uiState = uiState.copy(result = result)
    }
    }
    UiState UI

    View Slide

  101. ©MIXI
    UI ViewModel
    101
    val viewModel: OmikujiViewModel = viewModel()
    val uiState = viewModel.uiState
    Text(text = uiState.result)
    var result by remember { mutableStateOf("") }
    Text(text = result)
    Before
    After Compose
    ViewModel

    View Slide

  102. ©MIXI
    Button(onClick = viewModel::pick)
    UI ViewModel
    102
    Button(onClick = {
    viewModel.pick()
    })
    Button(onClick = {
    result = listOf(" ", " ", ...).random()
    })
    Before
    After OK

    View Slide

  103. ©MIXI
    103
    UI UI
    ViewModel
    app.omikuji

    View Slide

  104. ©MIXI
    7.1 : ToDo
    104

    View Slide

  105. ©MIXI
    7.1 : ToDo
    app.todo
    105
    ToDoScreen
    ToDoViewModel
    uiState
    l
    l UI
    l UI
    l
    l
    l
    ToDoUiState

    View Slide

  106. ©MIXI
    7.2 ( )
    5.1 LoginScreen
    106
    LoginScreen
    LoginViewModel
    uiState
    l
    l UI
    l UI
    l
    LoginUiState

    View Slide

  107. ©MIXI
    107
    , ,
    Android
    l UI
    l
    UI
    UI
    l
    (DB ) ( )

    View Slide

  108. 8

    View Slide

  109. ©MIXI
    109
    UI
    ViewModel
    ( )
    UI

    View Slide

  110. ©MIXI
    src/main/java/jp/co/mixi/androidtraining/omikuji/ui/OmikujiViewModel.kt
    110
    src/test/java/jp/co/mixi/androidtraining/omikuji/ui/OmikujiViewModelTest.kt
    ViewModel
    ViewModel
    Android Studio
    "Android" "Project"

    View Slide

  111. ©MIXI
    ViewModel
    111
    class OmikujiViewModelTest {
    private val viewModel = OmikujiViewModel()
    @Test
    fun testPick() {
    assertEquals("", viewModel.uiState.result)
    viewModel.pick()
    assertNotEquals("", viewModel.uiState.result)
    }
    }

    View Slide

  112. ©MIXI
    ViewModel
    112
    class OmikujiViewModelTest {
    private val viewModel = OmikujiViewModel()
    @Test
    fun testPick() {
    assertEquals("", viewModel.uiState.result)
    viewModel.pick()
    assertNotEquals("", viewModel.uiState.result)
    }
    }
    JUnit 4 (Java )
    API

    View Slide

  113. ©MIXI
    ViewModel
    113
    class OmikujiViewModelTest {
    private val viewModel = OmikujiViewModel()
    @Test
    fun testPick() {
    assertEquals("", viewModel.uiState.result)
    viewModel.pick()
    assertNotEquals("", viewModel.uiState.result)
    }
    }
    uiState

    View Slide

  114. ©MIXI
    ViewModel
    114
    class OmikujiViewModelTest {
    private val viewModel = OmikujiViewModel()
    @Test
    fun testPick() {
    assertEquals("", viewModel.uiState.result)
    viewModel.pick()
    assertEquals(" ", viewModel.uiState.result)
    }
    }

    View Slide

  115. ©MIXI
    115
    class OmikujiViewModel(
    private val repository: OmikujiRepository
    ) : ViewModel()
    DefaultOmikujiRepository FakeOmikujiRepository

    View Slide

  116. ©MIXI
    116
    interface OmikujiRepository {
    fun getResult(): String
    }
    class DefaultOmikujiRepository : OmikujiRepository {
    override fun getResult(): String {
    return listOf(" ", " ", ...).random()
    }
    }
    class FakeOmikujiRepository : OmikujiRepository {
    override fun getResult(): String {
    return " "
    }
    }

    View Slide

  117. ©MIXI
    117
    class OmikujiViewModelTest {
    private val viewModel = OmikujiViewModel(FakeOmikujiRepository())
    @Test
    fun testPick() {
    assertEquals("", viewModel.uiState.result)
    viewModel.pick()
    assertEquals(" ", viewModel.uiState.result)
    }
    }

    View Slide

  118. ©MIXI
    118

    View Slide

  119. ©MIXI
    8.1
    7.1 ToDoViewModel
    119
    l
    l
    l
    l

    View Slide

  120. ©MIXI
    8.2 ( )
    7.2 LoginViewModel
    120
    l ID 3 7
    l ID 4 7
    l ID 4 8

    View Slide

  121. ©MIXI
    121
    (Android )
    UI
    : ViewModel, ,
    : src/test/java/
    : JUnit 4

    View Slide

  122. 9

    View Slide

  123. ©MIXI
    :
    123

    View Slide

  124. ©MIXI
    124
    data class WeatherUiState(
    val weather: String = "",
    val isLoading: Boolean = false
    )
    fun getWeather() {
    //
    uiState = uiState.copy(isLoading = true)
    //
    val weather = repository.getWeather()
    //
    uiState = uiState.copy(weather = weather, isLoading = false)
    }
    ViewModel

    View Slide

  125. ©MIXI
    125
    data class WeatherUiState(
    val weather: String = "",
    val isLoading: Boolean = false
    )
    fun getWeather() {
    //
    uiState = uiState.copy(isLoading = true)
    //
    val weather = repository.getWeather()
    //
    uiState = uiState.copy(weather = weather, isLoading = false)
    }
    ViewModel
    (UI )

    View Slide

  126. ©MIXI
    Kotlin
    126
    viewModelScope.launch {
    uiState = uiState.copy(isLoading = true)
    val weather = repository.getWeather()
    uiState = uiState.copy(weather = weather, isLoading = false)
    }
    uiState = uiState.copy(isLoading = true)
    val weather = repository.getWeather()
    uiState = uiState.copy(weather = weather, isLoading = false)

    View Slide

  127. ©MIXI
    Kotlin
    127
    viewModelScope.launch {
    uiState = uiState.copy(isLoading = true)
    val weather = repository.getWeather()
    uiState = uiState.copy(weather = weather, isLoading = false)
    }
    getWeather()

    View Slide

  128. ©MIXI
    128
    getWeather()

    View Slide

  129. ©MIXI
    129
    class WeatherRepository {
    suspend fun getWeather(): String {
    //
    }
    }
    suspend
    l suspend
    l suspend suspend

    View Slide

  130. ©MIXI
    suspend
    130
    Kotlin API
    delay(timeMillis = 2000) 2
    Ktor (HTTP ) API
    val response = client.request(urlString = "https://...")
    DB
    Jetpack Room (SQLite ) API
    val user = dao.getUser(userId = ...)

    View Slide

  131. ©MIXI
    131
    viewModelScope.launch {
    val weather = repository.getWeather()
    }
    ViewModel
    viewModelScope
    ( )

    View Slide

  132. ©MIXI
    132
    UI
    l
    l suspend
    l suspend
    l suspend
    l suspend
    suspend
    e.g. , DB

    View Slide

  133. 10

    View Slide

  134. ©MIXI
    :
    134

    View Slide

  135. ©MIXI
    135
    data class WeatherUiState(
    val weather: String = "",
    val isLoading: Boolean = false,
    val isError: Boolean = false
    )
    sealed class WeatherUiState {
    data class Success(val weather: String) : WeatherUiState()
    object Loading : WeatherUiState()
    object Error : WeatherUiState()
    }
    OK
    UiState

    View Slide

  136. ©MIXI
    136
    sealed class WeatherUiState {
    data class Success(val weather: String) : WeatherUiState()
    object Loading : WeatherUiState()
    object Error : WeatherUiState()
    }
    sealed class
    WeatherUiState
    WeatherUiState

    View Slide

  137. ©MIXI
    try-catch
    137
    fun getWeather() {
    viewModelScope.launch {
    uiState = WeatherUiState.Loading
    try {
    val weather = repository.getWeather()
    uiState = WeatherUiState.Success(weather = weather)
    } catch (error: SomeException) {
    uiState = WeatherUiState.Error
    }
    }
    }

    View Slide

  138. ©MIXI
    try-catch
    138
    fun getWeather() {
    viewModelScope.launch {
    uiState = WeatherUiState.Loading
    try {
    val weather = repository.getWeather()
    uiState = WeatherUiState.Success(weather = weather)
    } catch (error: SomeException) {
    uiState = WeatherUiState.Error
    }
    }
    }
    catch
    Exception catch
    throw (
    )

    View Slide

  139. ©MIXI
    UI
    when
    app.weather
    139
    @Composable
    fun WeatherScreen(...) {
    val uiState = viewModel.uiState
    when (uiState) {
    is WeatherUiState.Success -> SuccessScreen(...)
    is WeatherUiState.Loading -> LoadingScreen(...)
    is WeatherUiState.Error -> ErrorScreen(...)
    }
    }

    View Slide

  140. ©MIXI
    140
    try-catch
    sealed class / /

    View Slide

  141. 7
    8
    9
    10

    View Slide

  142. ©MIXI
    10.1 : SNS
    app.sns
    app.weather
    142
    TimelineScreen
    TimelineViewModel
    TimelineUiState
    TimelineRepository
    List
    l
    l UiState
    l suspend

    View Slide

  143. ©MIXI
    10.2 : / / UI
    app.sns /
    app.weather
    IOException throw
    143

    View Slide

  144. ©MIXI
    10.3 : SNS
    10.1 ViewModel
    app.weather
    : https://developer.android.com/kotlin/coroutines/test?hl=ja
    144
    l
    l UiState

    View Slide

  145. View Slide

  146. ©MIXI
    Compose, , , ,
    https://github.com/android/nowinandroid
    146
    https://github.com/android/architecture-samples
    Compose UI
    https://github.com/android/compose-samples
    Now in Android App
    Android Architecture Samples
    Jetpack Compose Samples

    View Slide

  147. ©MIXI
    https://android-developers.googleblog.com/
    147
    https://medium.com/androiddevelopers
    https://material.io/blog/
    Android Developers Blog
    Medium
    Material Design Blog
    https://blog.jetbrains.com/kotlin/
    Kotlin Blog

    View Slide