Link
Embed
Share
Beginning
This slide
Copy link URL
Copy link URL
Copy iframe embed code
Copy iframe embed code
Copy javascript embed code
Copy javascript embed code
Share
Tweet
Share
Tweet
Slide 1
Slide 1 text
Android 2023.4.26 Android Google LLC
Slide 2
Slide 2 text
©MIXI 2 2017 Vantage KARASTA 2015 Vantage M
Slide 3
Slide 3 text
No content
Slide 4
Slide 4 text
©MIXI 4 Android Android
Slide 5
Slide 5 text
No content
Slide 6
Slide 6 text
©MIXI 6 1 Android 2 3 UI 4 5 6 7 8 9 10
Slide 7
Slide 7 text
Android 1
Slide 8
Slide 8 text
©MIXI Android 8 Android Auto Android TV PC ChromeOS Wear OS ,
Slide 9
Slide 9 text
©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 ( )
Slide 10
Slide 10 text
©MIXI Android Studio IntelliJ IDEA ⾒ https://developer.android.com/studio 10
Slide 11
Slide 11 text
©MIXI 11 Android Studio APK (Android Application Package) AVD (Android Virtual Device)
Slide 12
Slide 12 text
©MIXI 12 Android Studio AAB (Android App Bundle) Google Play
Slide 13
Slide 13 text
©MIXI 13 Android Studio AAB (Android App Bundle) Google Play : : xxhdpi CPU: arm : : hdpi CPU: x86 APK
Slide 14
Slide 14 text
©MIXI 14 Android Studio AAB (Android App Bundle) Google Play l l : : xxhdpi CPU: arm : : hdpi CPU: x86
Slide 15
Slide 15 text
©MIXI Kotlin Android (2017 ) Java 15 Kotlin l : l Null : l Java : Kotlin Java Java Kotlin
Slide 16
Slide 16 text
©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
Slide 17
Slide 17 text
©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
Slide 18
Slide 18 text
©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
Slide 19
Slide 19 text
2
Slide 20
Slide 20 text
©MIXI Android Studio New Project 20
Slide 21
Slide 21 text
©MIXI Empty Activity (Activity ) Jetpack Compose 21
Slide 22
Slide 22 text
©MIXI Name Package name ID { }.{ } : jp.co.mixi.karasta Minimum SDK 22
Slide 23
Slide 23 text
©MIXI AVD ( ) ⾒ https://developer.android.com/studio/run/managing-avds?hl=ja 23 AVD
Slide 24
Slide 24 text
©MIXI 24 , , Kotlin ,
Slide 25
Slide 25 text
©MIXI ( ) 1. https://developer.android.com/studio/debug/dev-options?hl=ja#enable 2. USB ON 3. USB Android Studio 25 1. USB
Slide 26
Slide 26 text
©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
Slide 27
Slide 27 text
UI 3
Slide 28
Slide 28 text
©MIXI : 1. Android Studio Get from VCS 28 2. URL
[email protected]
:mixigroup/2023AndroidTraining.git git clone OK 3. app.ui 1
Slide 29
Slide 29 text
©MIXI Jetpack l l 29 app Android 13 Android 12 Android 11 if else if else ... app Android 13 Android 12 Android 11 Jetpack
Slide 30
Slide 30 text
©MIXI Jetpack Compose Jetpack Kotlin UI 2021 UI ( ) https://developer.android.com/jetpack/compose?hl=ja 30
Slide 31
Slide 31 text
©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
Slide 32
Slide 32 text
©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
Slide 33
Slide 33 text
©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) )
Slide 34
Slide 34 text
©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
Slide 35
Slide 35 text
©MIXI Composable 35 // modifier RedText( text = "Red text" ) // modifier RedText( text = "Red text with blue background", modifier = Modifier.background(Color.Blue) ) text = modifier API
Slide 36
Slide 36 text
©MIXI Composable Composable Composable Composable API ( ) 36 Button { Text(text = "Hello") } Composable
Slide 37
Slide 37 text
©MIXI Composable 37 @Composable fun Button( ... content: @Composable () -> Unit ) Button(content = { Text(text = "Hello") }) Button() { Text(text = "Hello") } Button { Text(text = "Hello") } ( ) -> () -> Unit { -> } () ()
Slide 38
Slide 38 text
©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
Slide 39
Slide 39 text
©MIXI DP Px 39 DP : density-independent pixels : : : :
Slide 40
Slide 40 text
©MIXI 40 SP : scalable pixels
Slide 41
Slide 41 text
©MIXI Button, Checkbox, TopAppBar Composable 41 API https://developer.android.com/reference/kotlin/androidx/compose/material3/package-summary https://m3.material.io/components
Slide 42
Slide 42 text
©MIXI Composable Composable 42 Column Row
Slide 43
Slide 43 text
©MIXI Composable 43 Column( horizontalAlignment = Alignment.CenterHorizontally, verticalArrangement = Arrangement.spacedBy(8.dp) ) { Text(text = "Top") Text(text = "Center") Text(text = "Bottom") } Composable (36 )
Slide 44
Slide 44 text
©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") }
Slide 45
Slide 45 text
©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 ⾒
Slide 46
Slide 46 text
©MIXI Composable 46 Row( horizontalArrangement = Arrangement.spacedBy(8.dp), verticalAlignment = Alignment.CenterVertically ) { Text(text = "Left") Text(text = "Center") Text(text = "Right") } Row : Column
Slide 47
Slide 47 text
©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
Slide 48
Slide 48 text
©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) } }
Slide 49
Slide 49 text
©MIXI Composable @Preview 築 49
Slide 50
Slide 50 text
©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
Slide 51
Slide 51 text
©MIXI Android Studio Tips Option + Enter import 51 Unresolved reference Command + B Command +
Slide 52
Slide 52 text
©MIXI 3.2 ( ) API https://developer.android.com/reference/kotlin/androidx/compose/material3/package-summary 52
Slide 53
Slide 53 text
©MIXI UI 53 Jetpack UI Kotlin Jetpack Compose Composable UI Modifier Composable Column , Row , LazyColumn / LazyRow DP , SP
Slide 54
Slide 54 text
4
Slide 55
Slide 55 text
©MIXI Android 55 ( ) l String resource l Drawable resource l Raw resource src/main/res/
Slide 56
Slide 56 text
©MIXI res/values/strings.xml 56 ... Text(text = stringResource(id = R.string.login)) Text(text = stringResource(id = R.string.settings)) UI
Slide 57
Slide 57 text
©MIXI 57 strings.xml strings.xml 1 2
Slide 58
Slide 58 text
©MIXI 58 strings.xml Settings res/values/strings.xml res/values-ja/strings.xml
Slide 59
Slide 59 text
©MIXI 59 : JPG, PNG, WebP : SVG
Slide 60
Slide 60 text
©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 ( )
Slide 61
Slide 61 text
©MIXI VectorDrawable 61 SVG or
Slide 62
Slide 62 text
©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
Slide 63
Slide 63 text
©MIXI Modifier 63 Image( ... modifier = Modifier.clip(CircleShape) ) Image( ... modifier = Modifier.clip(RoundedCornerShape(size = 8.dp)) )
Slide 64
Slide 64 text
©MIXI 4.1 3.1 BookItem 3.1 ⾒ answer/3.1
Slide 65
Slide 65 text
©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
Slide 66
Slide 66 text
©MIXI 4.3 ( ) 4.1 https://developer.android.com/training/basics/supporting-devices/languages?hl=ja 66 l l
Slide 67
Slide 67 text
©MIXI 67 res/values/strings.xml l l Android Studio VectorDrawable
Slide 68
Slide 68 text
5
Slide 69
Slide 69 text
©MIXI Text(text = " ") Composable (Recompose) UI 69 Text(text = " ")
Slide 70
Slide 70 text
©MIXI 70 0 1 1 2
Slide 71
Slide 71 text
©MIXI 1 : 71 var count = 0 Button(onClick = { count++ }) { Text(text = count.toString()) } count Recompose val : var : 0 0
Slide 72
Slide 72 text
©MIXI 1 : 72 var count by remember { mutableStateOf(0) } Button(onClick = { count++ }) { Text(text = count.toString()) } MutableState Compose Recompose (UI )
Slide 73
Slide 73 text
©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
Slide 74
Slide 74 text
©MIXI 1 : 74 var count by remember { mutableStateOf(0) } Button(onClick = { count++ }) { Text(text = count.toString()) } 0 1
Slide 75
Slide 75 text
©MIXI var text by remember { mutableStateOf("") } TextField( value = text, onValueChange = { value -> text = value } ) 2 : 75
Slide 76
Slide 76 text
©MIXI 5.1 app.login LoginScreen l l ID 4 8 ( ) 76
Slide 77
Slide 77 text
©MIXI 5.2 ( ) UI https://developer.android.com/reference/kotlin/androidx/compose/material3/package-summary 77 l Switch l Checkbox l Slider
Slide 78
Slide 78 text
©MIXI 78 Composable (Recompose) UI MutableState Recompose var state by remember { mutableStateOf( ) } UI Composable onClick onValueChange e.g. Button, TextField, Switch UI UI
Slide 79
Slide 79 text
6
Slide 80
Slide 80 text
©MIXI 80
Slide 81
Slide 81 text
©MIXI 81
Slide 82
Slide 82 text
©MIXI 82 1 2 3
Slide 83
Slide 83 text
©MIXI 83 :
Slide 84
Slide 84 text
©MIXI 84 Log.v(TAG, " ") Log.d(TAG, " ") Log.i(TAG, " ") Log.w(TAG, " ") Log.e(TAG, " ") ( )
Slide 85
Slide 85 text
©MIXI package:mine 85 package: tag: Log level:
Slide 86
Slide 86 text
©MIXI 86 l l l l
Slide 87
Slide 87 text
7
Slide 88
Slide 88 text
©MIXI ( ) 88 A B A B l l UI l
Slide 89
Slide 89 text
©MIXI https://developer.android.com/topic/architecture?hl=ja 89 UI l UI l l UI l l UI l ( )
Slide 90
Slide 90 text
©MIXI UI 90 UI UI Compose l UI l UI ViewModel l UI l UI UI
Slide 91
Slide 91 text
©MIXI 91 UI UI ( )
Slide 92
Slide 92 text
©MIXI UI 92 Jetpack Room SQLite Jetpack DataStore Key-Value Retrofit HTTP Ktor Kotlin Kotlin HTTP
Slide 93
Slide 93 text
©MIXI : ver. 93 Column(...) { var result by remember { mutableStateOf("") } Text(text = result) Button(onClick = { result = listOf(" ", " ", ...).random() }) { Text(text = stringResource(R.string.pick_omikuji)) } }
Slide 94
Slide 94 text
©MIXI 94 UI l l ( ) l UI l
Slide 95
Slide 95 text
©MIXI ( ) 95 class OmikujiRepository { fun getResult(): String { return listOf(" 規", "規", ...).random() } }
Slide 96
Slide 96 text
©MIXI UI 96 data class OmikujiUiState( val result: String = "" ) equals() copy() OK
Slide 97
Slide 97 text
©MIXI Jetpack 97 class OmikujiViewModel() : ViewModel() { ... } UI ViewModel ViewModel
Slide 98
Slide 98 text
©MIXI ViewModel 98 class OmikujiViewModel( private val repository: OmikujiRepository = OmikujiRepository() ) : ViewModel() { ... } (DI) Hilt DI
Slide 99
Slide 99 text
©MIXI UiState MutableState 99 class OmikujiViewModel(...) : ViewModel() { var uiState by mutableStateOf(OmikujiUiState()) private set } MutableStateFlow l MutableState Compose API l MutableStateFlow Kotlin API
Slide 100
Slide 100 text
©MIXI UiState ViewModel 100 class OmikujiViewModel(...) : ViewModel() { ... fun pick() { val result = repository.getResult() uiState = uiState.copy(result = result) } } UiState UI
Slide 101
Slide 101 text
©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
Slide 102
Slide 102 text
©MIXI Button(onClick = viewModel::pick) UI ViewModel 102 Button(onClick = { viewModel.pick() }) Button(onClick = { result = listOf(" ", " ", ...).random() }) Before After OK
Slide 103
Slide 103 text
©MIXI 103 UI UI ViewModel app.omikuji
Slide 104
Slide 104 text
©MIXI 7.1 : ToDo 104
Slide 105
Slide 105 text
©MIXI 7.1 : ToDo app.todo 105 ToDoScreen ToDoViewModel uiState l l UI l UI l l l ToDoUiState
Slide 106
Slide 106 text
©MIXI 7.2 ( ) 5.1 LoginScreen 106 LoginScreen LoginViewModel uiState l l UI l UI l LoginUiState
Slide 107
Slide 107 text
©MIXI 107 , , Android l UI l UI UI l (DB ) ( )
Slide 108
Slide 108 text
8
Slide 109
Slide 109 text
©MIXI 109 UI ViewModel ( ) UI
Slide 110
Slide 110 text
©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"
Slide 111
Slide 111 text
©MIXI ViewModel 111 class OmikujiViewModelTest { private val viewModel = OmikujiViewModel() @Test fun testPick() { assertEquals("", viewModel.uiState.result) viewModel.pick() assertNotEquals("", viewModel.uiState.result) } }
Slide 112
Slide 112 text
©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
Slide 113
Slide 113 text
©MIXI ViewModel 113 class OmikujiViewModelTest { private val viewModel = OmikujiViewModel() @Test fun testPick() { assertEquals("", viewModel.uiState.result) viewModel.pick() assertNotEquals("", viewModel.uiState.result) } } uiState
Slide 114
Slide 114 text
©MIXI ViewModel 114 class OmikujiViewModelTest { private val viewModel = OmikujiViewModel() @Test fun testPick() { assertEquals("", viewModel.uiState.result) viewModel.pick() assertEquals(" ", viewModel.uiState.result) } }
Slide 115
Slide 115 text
©MIXI 115 class OmikujiViewModel( private val repository: OmikujiRepository ) : ViewModel() DefaultOmikujiRepository FakeOmikujiRepository
Slide 116
Slide 116 text
©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 " " } }
Slide 117
Slide 117 text
©MIXI 117 class OmikujiViewModelTest { private val viewModel = OmikujiViewModel(FakeOmikujiRepository()) @Test fun testPick() { assertEquals("", viewModel.uiState.result) viewModel.pick() assertEquals(" ", viewModel.uiState.result) } }
Slide 118
Slide 118 text
©MIXI 118
Slide 119
Slide 119 text
©MIXI 8.1 7.1 ToDoViewModel 119 l l l l
Slide 120
Slide 120 text
©MIXI 8.2 ( ) 7.2 LoginViewModel 120 l ID 3 7 l ID 4 7 l ID 4 8
Slide 121
Slide 121 text
©MIXI 121 (Android ) UI : ViewModel, , : src/test/java/ : JUnit 4
Slide 122
Slide 122 text
9
Slide 123
Slide 123 text
©MIXI : 123
Slide 124
Slide 124 text
©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
Slide 125
Slide 125 text
©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 )
Slide 126
Slide 126 text
©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)
Slide 127
Slide 127 text
©MIXI Kotlin 127 viewModelScope.launch { uiState = uiState.copy(isLoading = true) val weather = repository.getWeather() uiState = uiState.copy(weather = weather, isLoading = false) } getWeather()
Slide 128
Slide 128 text
©MIXI 128 getWeather()
Slide 129
Slide 129 text
©MIXI 129 class WeatherRepository { suspend fun getWeather(): String { // } } suspend l suspend l suspend suspend
Slide 130
Slide 130 text
©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 = ...)
Slide 131
Slide 131 text
©MIXI 131 viewModelScope.launch { val weather = repository.getWeather() } ViewModel viewModelScope ( )
Slide 132
Slide 132 text
©MIXI 132 UI l l suspend l suspend l suspend l suspend suspend e.g. , DB
Slide 133
Slide 133 text
10
Slide 134
Slide 134 text
©MIXI : 134
Slide 135
Slide 135 text
©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
Slide 136
Slide 136 text
©MIXI 136 sealed class WeatherUiState { data class Success(val weather: String) : WeatherUiState() object Loading : WeatherUiState() object Error : WeatherUiState() } sealed class WeatherUiState WeatherUiState
Slide 137
Slide 137 text
©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 } } }
Slide 138
Slide 138 text
©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 ( )
Slide 139
Slide 139 text
©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(...) } }
Slide 140
Slide 140 text
©MIXI 140 try-catch sealed class / /
Slide 141
Slide 141 text
7 8 9 10
Slide 142
Slide 142 text
©MIXI 10.1 : SNS app.sns app.weather 142 TimelineScreen TimelineViewModel TimelineUiState TimelineRepository List l l UiState l suspend
Slide 143
Slide 143 text
©MIXI 10.2 : / / UI app.sns / app.weather IOException throw 143
Slide 144
Slide 144 text
©MIXI 10.3 : SNS 10.1 ViewModel app.weather : https://developer.android.com/kotlin/coroutines/test?hl=ja 144 l l UiState
Slide 145
Slide 145 text
No content
Slide 146
Slide 146 text
©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
Slide 147
Slide 147 text
©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