From 50ca441af4418464c58d9277bd73bf72421fca0a Mon Sep 17 00:00:00 2001 From: kangyuri1114 Date: Fri, 26 Apr 2024 02:17:31 +0900 Subject: [PATCH 1/6] =?UTF-8?q?=EC=95=84=EC=A7=81=20=EB=B6=99=EC=9D=B4?= =?UTF-8?q?=EB=8A=94=20=EC=A4=91..=20api=20..=20=EC=98=A4=EB=9E=9C?= =?UTF-8?q?=EB=A7=8C=EC=9D=B4=EB=9D=BC=20=EB=8B=A4=20=EA=B9=8C=EB=A8=B9...?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .idea/deploymentTargetDropDown.xml | 3 -- .idea/encodings.xml | 1 + app/build.gradle.kts | 17 ++++++++ app/src/main/AndroidManifest.xml | 2 + .../sopt/do_sopt_compose/data/ApiFactory.kt | 41 +++++++++++++++++++ .../sopt/do_sopt_compose/data/ApiService.kt | 11 +++++ .../do_sopt_compose/data/PeopleRepository.kt | 8 ++++ .../data/dto/ReponsePeopleDto.kt | 24 +++++++++++ .../navigation/MainNavigation.kt | 2 + .../ui/pages/doandroid/DoAndroid.kt | 3 +- .../ui/pages/doandroid/DoAndroidViewModel.kt | 20 +++++++++ 11 files changed, 128 insertions(+), 4 deletions(-) create mode 100644 app/src/main/java/org/sopt/do_sopt_compose/data/ApiFactory.kt create mode 100644 app/src/main/java/org/sopt/do_sopt_compose/data/ApiService.kt create mode 100644 app/src/main/java/org/sopt/do_sopt_compose/data/PeopleRepository.kt create mode 100644 app/src/main/java/org/sopt/do_sopt_compose/data/dto/ReponsePeopleDto.kt create mode 100644 app/src/main/java/org/sopt/do_sopt_compose/ui/pages/doandroid/DoAndroidViewModel.kt diff --git a/.idea/deploymentTargetDropDown.xml b/.idea/deploymentTargetDropDown.xml index c4334ac..0c0c338 100644 --- a/.idea/deploymentTargetDropDown.xml +++ b/.idea/deploymentTargetDropDown.xml @@ -2,9 +2,6 @@ - - - diff --git a/.idea/encodings.xml b/.idea/encodings.xml index 97626ba..b4206a4 100644 --- a/.idea/encodings.xml +++ b/.idea/encodings.xml @@ -1,6 +1,7 @@ + \ No newline at end of file diff --git a/app/build.gradle.kts b/app/build.gradle.kts index abb5cd5..bbfae5b 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -1,6 +1,9 @@ +import com.android.build.gradle.internal.cxx.configure.gradleLocalProperties + plugins { id("com.android.application") id("org.jetbrains.kotlin.android") + id("org.jetbrains.kotlin.plugin.serialization") version "1.6.0" } android { @@ -18,6 +21,9 @@ android { vectorDrawables { useSupportLibrary = true } + + buildConfigField("String", "BASE_URL", gradleLocalProperties(rootDir).getProperty("BASE_URL")) + } buildTypes { @@ -29,6 +35,7 @@ android { ) } } + compileOptions { sourceCompatibility = JavaVersion.VERSION_1_8 targetCompatibility = JavaVersion.VERSION_1_8 @@ -38,6 +45,7 @@ android { } buildFeatures { compose = true + buildConfig = true } composeOptions { kotlinCompilerExtensionVersion = "1.5.1" @@ -77,4 +85,13 @@ dependencies { implementation("org.orbit-mvi:orbit-viewmodel:4.4.0") implementation("org.orbit-mvi:orbit-compose:4.4.0") testImplementation("org.orbit-mvi:orbit-test:4.4.0") + + // openApi + implementation("io.coil-kt:coil:2.6.0") + implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.6.3") + implementation("com.squareup.okhttp3:okhttp:4.12.0") + implementation("com.squareup.okhttp3:logging-interceptor:4.12.0") + implementation("com.squareup.retrofit2:retrofit:2.11.0") + implementation("com.jakewharton.retrofit:retrofit2-kotlinx-serialization-converter:1.0.0") + } \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 0602202..64622d8 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -2,6 +2,8 @@ + + + Log.d("Retrofit2", "CONNECTION INFO -> $message") + } + loggingInterceptor.level = HttpLoggingInterceptor.Level.BODY + return loggingInterceptor + } + + private val okHttpClient = OkHttpClient.Builder() + .addInterceptor(getLogOkHttpClient()) + .build() + + fun retrofit(url: String): Retrofit = + Retrofit.Builder() + .baseUrl(url) + .client(okHttpClient) + .addConverterFactory(Json.asConverterFactory("application/json".toMediaType())) + .build() + + inline fun create(url: B): T = + retrofit(url.toString()).create(T::class.java) +} + +object ServicePool { + val apiService = ApiFactory.create(BASE_URL) +} \ No newline at end of file diff --git a/app/src/main/java/org/sopt/do_sopt_compose/data/ApiService.kt b/app/src/main/java/org/sopt/do_sopt_compose/data/ApiService.kt new file mode 100644 index 0000000..a427a22 --- /dev/null +++ b/app/src/main/java/org/sopt/do_sopt_compose/data/ApiService.kt @@ -0,0 +1,11 @@ +package org.sopt.do_sopt_compose.data + +import org.sopt.do_sopt_compose.data.dto.ReponsePeopleDto +import retrofit2.Call +import retrofit2.http.GET +import retrofit2.http.Query + +interface ApiService { + @GET("/api/users") + fun getUsers(@Query("page") page: Int): Call +} \ No newline at end of file diff --git a/app/src/main/java/org/sopt/do_sopt_compose/data/PeopleRepository.kt b/app/src/main/java/org/sopt/do_sopt_compose/data/PeopleRepository.kt new file mode 100644 index 0000000..9a28a98 --- /dev/null +++ b/app/src/main/java/org/sopt/do_sopt_compose/data/PeopleRepository.kt @@ -0,0 +1,8 @@ +package org.sopt.do_sopt_compose.data + +class PeopleRepository { + + private val apiService = ServicePool.apiService + + suspend fun getUsers(page: Int) = apiService.getUsers(page) +} \ No newline at end of file diff --git a/app/src/main/java/org/sopt/do_sopt_compose/data/dto/ReponsePeopleDto.kt b/app/src/main/java/org/sopt/do_sopt_compose/data/dto/ReponsePeopleDto.kt new file mode 100644 index 0000000..026ec89 --- /dev/null +++ b/app/src/main/java/org/sopt/do_sopt_compose/data/dto/ReponsePeopleDto.kt @@ -0,0 +1,24 @@ +package org.sopt.do_sopt_compose.data.dto + + +data class ReponsePeopleDto( + val page: Int, + val per_page: Int, + val total: Int, + val total_pages: Int, + val data: List, + val support: Support +) + +data class User( + val id: Int, + val email: String, + val first_name: String, + val last_name: String, + val avatar: String +) + +data class Support( + val url: String, + val text: String +) diff --git a/app/src/main/java/org/sopt/do_sopt_compose/navigation/MainNavigation.kt b/app/src/main/java/org/sopt/do_sopt_compose/navigation/MainNavigation.kt index 87d4d3a..200146f 100644 --- a/app/src/main/java/org/sopt/do_sopt_compose/navigation/MainNavigation.kt +++ b/app/src/main/java/org/sopt/do_sopt_compose/navigation/MainNavigation.kt @@ -7,6 +7,7 @@ import androidx.navigation.NavHostController import androidx.navigation.compose.NavHost import androidx.navigation.compose.composable import org.sopt.do_sopt_compose.ui.pages.doandroid.DoAndroid +import org.sopt.do_sopt_compose.ui.pages.doandroid.DoAndroidViewModel import org.sopt.do_sopt_compose.ui.pages.home.HomePage import org.sopt.do_sopt_compose.ui.pages.login.LoginPage import org.sopt.do_sopt_compose.ui.pages.mypage.MainPage @@ -52,6 +53,7 @@ private fun NavGraphBuilder.addDo(navController: NavController) { composable(route = BottomNaviItems.Do.route) { DoAndroid( navController = navController, + doAndroidViewModel = DoAndroidViewModel(), ) } } diff --git a/app/src/main/java/org/sopt/do_sopt_compose/ui/pages/doandroid/DoAndroid.kt b/app/src/main/java/org/sopt/do_sopt_compose/ui/pages/doandroid/DoAndroid.kt index 30c5a01..7b2c212 100644 --- a/app/src/main/java/org/sopt/do_sopt_compose/ui/pages/doandroid/DoAndroid.kt +++ b/app/src/main/java/org/sopt/do_sopt_compose/ui/pages/doandroid/DoAndroid.kt @@ -13,6 +13,7 @@ import org.sopt.do_sopt_compose.navigation.BottomNavigation @Composable fun DoAndroid( navController: NavController, + doAndroidViewModel: DoAndroidViewModel ) { Scaffold( bottomBar = { BottomNavigation(navController = navController) }, @@ -22,7 +23,7 @@ fun DoAndroid( .fillMaxSize() .padding(it), ) { - Text(text = "Do") + Text(text = "Do Android") } } ) diff --git a/app/src/main/java/org/sopt/do_sopt_compose/ui/pages/doandroid/DoAndroidViewModel.kt b/app/src/main/java/org/sopt/do_sopt_compose/ui/pages/doandroid/DoAndroidViewModel.kt new file mode 100644 index 0000000..0c3b5a5 --- /dev/null +++ b/app/src/main/java/org/sopt/do_sopt_compose/ui/pages/doandroid/DoAndroidViewModel.kt @@ -0,0 +1,20 @@ +package org.sopt.do_sopt_compose.ui.pages.doandroid + +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import kotlinx.coroutines.launch +import org.sopt.do_sopt_compose.data.PeopleRepository + +class DoAndroidViewModel: ViewModel() { + + private val peopleRepository = PeopleRepository() + + init { + getPeople(1) + } + fun getPeople(page: Int) { + viewModelScope.launch { + val peopleList = peopleRepository.getUsers(page) + } + } +} \ No newline at end of file From 75f91c38ac50a56a1178eec7f6079f4ed429d18c Mon Sep 17 00:00:00 2001 From: kangyuri1114 Date: Sun, 28 Apr 2024 01:26:12 +0900 Subject: [PATCH 2/6] =?UTF-8?q?=ED=86=B5=EC=8B=A0=20=EC=84=B1=EA=B3=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/build.gradle.kts | 25 ++++++++--- .../sopt/do_sopt_compose/data/ApiFactory.kt | 5 ++- .../sopt/do_sopt_compose/data/ApiService.kt | 9 ++-- .../do_sopt_compose/data/PeopleRepository.kt | 3 +- .../data/dto/ReponsePeopleDto.kt | 24 ----------- .../data/dto/ResponsePeopleDto.kt | 43 +++++++++++++++++++ 6 files changed, 71 insertions(+), 38 deletions(-) delete mode 100644 app/src/main/java/org/sopt/do_sopt_compose/data/dto/ReponsePeopleDto.kt create mode 100644 app/src/main/java/org/sopt/do_sopt_compose/data/dto/ResponsePeopleDto.kt diff --git a/app/build.gradle.kts b/app/build.gradle.kts index bbfae5b..74bc860 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -3,7 +3,8 @@ import com.android.build.gradle.internal.cxx.configure.gradleLocalProperties plugins { id("com.android.application") id("org.jetbrains.kotlin.android") - id("org.jetbrains.kotlin.plugin.serialization") version "1.6.0" + id ("kotlin-parcelize") + id("org.jetbrains.kotlin.plugin.serialization") version "1.8.0" } android { @@ -87,11 +88,21 @@ dependencies { testImplementation("org.orbit-mvi:orbit-test:4.4.0") // openApi - implementation("io.coil-kt:coil:2.6.0") - implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.6.3") - implementation("com.squareup.okhttp3:okhttp:4.12.0") - implementation("com.squareup.okhttp3:logging-interceptor:4.12.0") - implementation("com.squareup.retrofit2:retrofit:2.11.0") - implementation("com.jakewharton.retrofit:retrofit2-kotlinx-serialization-converter:1.0.0") + implementation ("com.squareup.retrofit2:retrofit:2.9.0") + implementation ("org.jetbrains.kotlinx:kotlinx-serialization-json:1.4.1") + implementation ("com.jakewharton.retrofit:retrofit2-kotlinx-serialization-converter:1.0.0") + + // define a BOM and its version + implementation(platform("com.squareup.okhttp3:okhttp-bom:4.10.0")) + + // define any required OkHttp artifacts without version + implementation("com.squareup.okhttp3:okhttp") + implementation("com.squareup.okhttp3:logging-interceptor") + + //OkHttp: 통신 로그 확인하기 위함 + implementation ("com.squareup.okhttp3:okhttp:4.11.0") + implementation ("com.squareup.okhttp3:logging-interceptor:4.10.0") + implementation ("com.squareup.retrofit2:converter-gson:2.1.0") + } \ No newline at end of file diff --git a/app/src/main/java/org/sopt/do_sopt_compose/data/ApiFactory.kt b/app/src/main/java/org/sopt/do_sopt_compose/data/ApiFactory.kt index be8d1dd..3d50c38 100644 --- a/app/src/main/java/org/sopt/do_sopt_compose/data/ApiFactory.kt +++ b/app/src/main/java/org/sopt/do_sopt_compose/data/ApiFactory.kt @@ -7,9 +7,9 @@ import okhttp3.Interceptor import okhttp3.MediaType.Companion.toMediaType import okhttp3.OkHttpClient import okhttp3.logging.HttpLoggingInterceptor -import org.sopt.do_sopt_compose.BuildConfig import org.sopt.do_sopt_compose.BuildConfig.BASE_URL import retrofit2.Retrofit +import retrofit2.converter.gson.GsonConverterFactory object ApiFactory { @@ -29,7 +29,8 @@ object ApiFactory { Retrofit.Builder() .baseUrl(url) .client(okHttpClient) - .addConverterFactory(Json.asConverterFactory("application/json".toMediaType())) + //.addConverterFactory(Json.asConverterFactory("application/json".toMediaType())) + .addConverterFactory(GsonConverterFactory.create()) .build() inline fun create(url: B): T = diff --git a/app/src/main/java/org/sopt/do_sopt_compose/data/ApiService.kt b/app/src/main/java/org/sopt/do_sopt_compose/data/ApiService.kt index a427a22..4a6cc0e 100644 --- a/app/src/main/java/org/sopt/do_sopt_compose/data/ApiService.kt +++ b/app/src/main/java/org/sopt/do_sopt_compose/data/ApiService.kt @@ -1,11 +1,14 @@ package org.sopt.do_sopt_compose.data -import org.sopt.do_sopt_compose.data.dto.ReponsePeopleDto +import org.sopt.do_sopt_compose.data.dto.ResponsePeopleDto import retrofit2.Call import retrofit2.http.GET import retrofit2.http.Query interface ApiService { - @GET("/api/users") - fun getUsers(@Query("page") page: Int): Call + @GET("users") + suspend fun getUsers( + @Query("page") page: Int, + @Query("per_page") perPage: Int, + ): ResponsePeopleDto } \ No newline at end of file diff --git a/app/src/main/java/org/sopt/do_sopt_compose/data/PeopleRepository.kt b/app/src/main/java/org/sopt/do_sopt_compose/data/PeopleRepository.kt index 9a28a98..21ea5c6 100644 --- a/app/src/main/java/org/sopt/do_sopt_compose/data/PeopleRepository.kt +++ b/app/src/main/java/org/sopt/do_sopt_compose/data/PeopleRepository.kt @@ -3,6 +3,5 @@ package org.sopt.do_sopt_compose.data class PeopleRepository { private val apiService = ServicePool.apiService - - suspend fun getUsers(page: Int) = apiService.getUsers(page) + suspend fun getUsers(page: Int) = apiService.getUsers(page, 10) } \ No newline at end of file diff --git a/app/src/main/java/org/sopt/do_sopt_compose/data/dto/ReponsePeopleDto.kt b/app/src/main/java/org/sopt/do_sopt_compose/data/dto/ReponsePeopleDto.kt deleted file mode 100644 index 026ec89..0000000 --- a/app/src/main/java/org/sopt/do_sopt_compose/data/dto/ReponsePeopleDto.kt +++ /dev/null @@ -1,24 +0,0 @@ -package org.sopt.do_sopt_compose.data.dto - - -data class ReponsePeopleDto( - val page: Int, - val per_page: Int, - val total: Int, - val total_pages: Int, - val data: List, - val support: Support -) - -data class User( - val id: Int, - val email: String, - val first_name: String, - val last_name: String, - val avatar: String -) - -data class Support( - val url: String, - val text: String -) diff --git a/app/src/main/java/org/sopt/do_sopt_compose/data/dto/ResponsePeopleDto.kt b/app/src/main/java/org/sopt/do_sopt_compose/data/dto/ResponsePeopleDto.kt new file mode 100644 index 0000000..1ecf091 --- /dev/null +++ b/app/src/main/java/org/sopt/do_sopt_compose/data/dto/ResponsePeopleDto.kt @@ -0,0 +1,43 @@ +package org.sopt.do_sopt_compose.data.dto + +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable + + +@Serializable +data class ResponsePeopleDto( + @SerialName("page") + val page: Int, + @SerialName("per_page") + val perPage: Int, + @SerialName("total") + val total: Int, + @SerialName("total_pages") + val totalPages: Int, + @SerialName("data") + val data: List, + @SerialName("support") + val support: Support, +) + +@Serializable +data class User( + @SerialName("id") + val id: Int, + @SerialName("email") + val email: String, + @SerialName("first_name") + val firstName: String, + @SerialName("last_name") + val lastName: String, + @SerialName("avatar") + val avatar: String, +) + +@Serializable +data class Support( + @SerialName("url") + val url: String, + @SerialName("text") + val text: String, +) From 32a682be7c44c05b9aff5a99e324f8c8ae35857e Mon Sep 17 00:00:00 2001 From: kangyuri1114 Date: Sun, 28 Apr 2024 01:55:54 +0900 Subject: [PATCH 3/6] =?UTF-8?q?=ED=86=B5=EC=8B=A0=20=EA=B2=B0=EA=B3=BC=20?= =?UTF-8?q?=EB=B7=B0=20=EB=B0=98=ED=99=98=20=EC=84=B1=EA=B3=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/build.gradle.kts | 2 +- .../ui/pages/doandroid/DoAndroid.kt | 69 ++++++++++++++++++- .../ui/pages/doandroid/DoAndroidViewModel.kt | 19 ++++- 3 files changed, 85 insertions(+), 5 deletions(-) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 74bc860..f0842aa 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -104,5 +104,5 @@ dependencies { implementation ("com.squareup.okhttp3:logging-interceptor:4.10.0") implementation ("com.squareup.retrofit2:converter-gson:2.1.0") - + implementation("io.coil-kt:coil-compose:2.6.0") } \ No newline at end of file diff --git a/app/src/main/java/org/sopt/do_sopt_compose/ui/pages/doandroid/DoAndroid.kt b/app/src/main/java/org/sopt/do_sopt_compose/ui/pages/doandroid/DoAndroid.kt index 7b2c212..193067d 100644 --- a/app/src/main/java/org/sopt/do_sopt_compose/ui/pages/doandroid/DoAndroid.kt +++ b/app/src/main/java/org/sopt/do_sopt_compose/ui/pages/doandroid/DoAndroid.kt @@ -1,13 +1,27 @@ package org.sopt.do_sopt_compose.ui.pages.doandroid +import androidx.compose.foundation.Image import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.lazy.items +import androidx.compose.material3.Card import androidx.compose.material3.Scaffold import androidx.compose.material3.Text import androidx.compose.runtime.Composable +import androidx.compose.runtime.collectAsState import androidx.compose.ui.Modifier +import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.unit.dp import androidx.navigation.NavController +import coil.compose.rememberAsyncImagePainter +import coil.request.ImageRequest +import org.sopt.do_sopt_compose.data.dto.User import org.sopt.do_sopt_compose.navigation.BottomNavigation @Composable @@ -15,6 +29,8 @@ fun DoAndroid( navController: NavController, doAndroidViewModel: DoAndroidViewModel ) { + val usersState = doAndroidViewModel.users.collectAsState() + Scaffold( bottomBar = { BottomNavigation(navController = navController) }, content = { @@ -23,8 +39,59 @@ fun DoAndroid( .fillMaxSize() .padding(it), ) { - Text(text = "Do Android") + UserList(users = usersState.value) } } ) } + +@Composable +fun UserList(users: List) { + LazyColumn { + items(users) { user -> + UserItem(user) + } + } +} + +@Composable +fun UserItem(user: User) { + Card( + modifier = Modifier + .fillMaxWidth() + .padding(8.dp) + ) { + Row( + modifier = Modifier.padding(8.dp) + ) { + // 프로필 이미지 표시 + Image( + painter = //placeholder() // 로딩 중에 표시할 이미지 + rememberAsyncImagePainter( + ImageRequest.Builder(LocalContext.current).data(data = user.avatar) + .apply(block = fun ImageRequest.Builder.() { + //placeholder() // 로딩 중에 표시할 이미지 + }).build() + ), + contentDescription = "Profile Picture", + modifier = Modifier + .size(64.dp) + .padding(end = 16.dp) + ) + Column { + Text( + text = "ID: ${user.id}", + modifier = Modifier.padding(bottom = 4.dp) + ) + Text( + text = "Name: ${user.firstName} ${user.lastName}", + modifier = Modifier.padding(bottom = 4.dp) + ) + Text( + text = "Email: ${user.email}", + modifier = Modifier.padding(bottom = 4.dp) + ) + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/org/sopt/do_sopt_compose/ui/pages/doandroid/DoAndroidViewModel.kt b/app/src/main/java/org/sopt/do_sopt_compose/ui/pages/doandroid/DoAndroidViewModel.kt index 0c3b5a5..f3af224 100644 --- a/app/src/main/java/org/sopt/do_sopt_compose/ui/pages/doandroid/DoAndroidViewModel.kt +++ b/app/src/main/java/org/sopt/do_sopt_compose/ui/pages/doandroid/DoAndroidViewModel.kt @@ -2,19 +2,32 @@ package org.sopt.do_sopt_compose.ui.pages.doandroid import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.launch import org.sopt.do_sopt_compose.data.PeopleRepository +import org.sopt.do_sopt_compose.data.dto.ResponsePeopleDto +import org.sopt.do_sopt_compose.data.dto.User -class DoAndroidViewModel: ViewModel() { +class DoAndroidViewModel : ViewModel() { private val peopleRepository = PeopleRepository() + private val _users = MutableStateFlow>(emptyList()) + val users = _users.asStateFlow() init { getPeople(1) } - fun getPeople(page: Int) { + + private fun getPeople(page: Int) { viewModelScope.launch { - val peopleList = peopleRepository.getUsers(page) + try { + _users.emit(peopleRepository.getUsers(page).data) + + } catch (e: Exception) { + _users.value = emptyList() + e.printStackTrace() } } +} } \ No newline at end of file From 5bc0fdce97d21755ae6fe0bf6c3fb683dff86a2e Mon Sep 17 00:00:00 2001 From: kangyuri1114 Date: Sun, 28 Apr 2024 20:41:06 +0900 Subject: [PATCH 4/6] =?UTF-8?q?orbit=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .idea/.name | 1 + .../sopt/do_sopt_compose/data/ApiFactory.kt | 6 +-- .../PeopleApiService.kt} | 5 +-- .../navigation/MainNavigation.kt | 5 +-- .../{DoAndroid.kt => DoAndroidScreen.kt} | 14 ++++--- .../ui/pages/doandroid/DoAndroidSideEffect.kt | 5 +++ .../ui/pages/doandroid/DoAndroidState.kt | 7 ++++ .../ui/pages/doandroid/DoAndroidViewModel.kt | 40 ++++++++++++++----- .../main/res/drawable/profile_background.xml | 9 +++++ 9 files changed, 68 insertions(+), 24 deletions(-) create mode 100644 .idea/.name rename app/src/main/java/org/sopt/do_sopt_compose/data/{ApiService.kt => service/PeopleApiService.kt} (75%) rename app/src/main/java/org/sopt/do_sopt_compose/ui/pages/doandroid/{DoAndroid.kt => DoAndroidScreen.kt} (88%) create mode 100644 app/src/main/java/org/sopt/do_sopt_compose/ui/pages/doandroid/DoAndroidSideEffect.kt create mode 100644 app/src/main/java/org/sopt/do_sopt_compose/ui/pages/doandroid/DoAndroidState.kt create mode 100644 app/src/main/res/drawable/profile_background.xml diff --git a/.idea/.name b/.idea/.name new file mode 100644 index 0000000..e139682 --- /dev/null +++ b/.idea/.name @@ -0,0 +1 @@ +do_sopt_compose \ No newline at end of file diff --git a/app/src/main/java/org/sopt/do_sopt_compose/data/ApiFactory.kt b/app/src/main/java/org/sopt/do_sopt_compose/data/ApiFactory.kt index 3d50c38..f0cb4a2 100644 --- a/app/src/main/java/org/sopt/do_sopt_compose/data/ApiFactory.kt +++ b/app/src/main/java/org/sopt/do_sopt_compose/data/ApiFactory.kt @@ -1,13 +1,11 @@ package org.sopt.do_sopt_compose.data import android.util.Log -import com.jakewharton.retrofit2.converter.kotlinx.serialization.asConverterFactory -import kotlinx.serialization.json.Json import okhttp3.Interceptor -import okhttp3.MediaType.Companion.toMediaType import okhttp3.OkHttpClient import okhttp3.logging.HttpLoggingInterceptor import org.sopt.do_sopt_compose.BuildConfig.BASE_URL +import org.sopt.do_sopt_compose.data.service.PeopleApiService import retrofit2.Retrofit import retrofit2.converter.gson.GsonConverterFactory @@ -38,5 +36,5 @@ object ApiFactory { } object ServicePool { - val apiService = ApiFactory.create(BASE_URL) + val apiService = ApiFactory.create(BASE_URL) } \ No newline at end of file diff --git a/app/src/main/java/org/sopt/do_sopt_compose/data/ApiService.kt b/app/src/main/java/org/sopt/do_sopt_compose/data/service/PeopleApiService.kt similarity index 75% rename from app/src/main/java/org/sopt/do_sopt_compose/data/ApiService.kt rename to app/src/main/java/org/sopt/do_sopt_compose/data/service/PeopleApiService.kt index 4a6cc0e..477d724 100644 --- a/app/src/main/java/org/sopt/do_sopt_compose/data/ApiService.kt +++ b/app/src/main/java/org/sopt/do_sopt_compose/data/service/PeopleApiService.kt @@ -1,11 +1,10 @@ -package org.sopt.do_sopt_compose.data +package org.sopt.do_sopt_compose.data.service import org.sopt.do_sopt_compose.data.dto.ResponsePeopleDto -import retrofit2.Call import retrofit2.http.GET import retrofit2.http.Query -interface ApiService { +interface PeopleApiService { @GET("users") suspend fun getUsers( @Query("page") page: Int, diff --git a/app/src/main/java/org/sopt/do_sopt_compose/navigation/MainNavigation.kt b/app/src/main/java/org/sopt/do_sopt_compose/navigation/MainNavigation.kt index 200146f..470bc45 100644 --- a/app/src/main/java/org/sopt/do_sopt_compose/navigation/MainNavigation.kt +++ b/app/src/main/java/org/sopt/do_sopt_compose/navigation/MainNavigation.kt @@ -6,7 +6,7 @@ import androidx.navigation.NavGraphBuilder import androidx.navigation.NavHostController import androidx.navigation.compose.NavHost import androidx.navigation.compose.composable -import org.sopt.do_sopt_compose.ui.pages.doandroid.DoAndroid +import org.sopt.do_sopt_compose.ui.pages.doandroid.DoAndroidScreen import org.sopt.do_sopt_compose.ui.pages.doandroid.DoAndroidViewModel import org.sopt.do_sopt_compose.ui.pages.home.HomePage import org.sopt.do_sopt_compose.ui.pages.login.LoginPage @@ -51,9 +51,8 @@ private fun NavGraphBuilder.addMain(navController: NavController) { private fun NavGraphBuilder.addDo(navController: NavController) { composable(route = BottomNaviItems.Do.route) { - DoAndroid( + DoAndroidScreen( navController = navController, - doAndroidViewModel = DoAndroidViewModel(), ) } } diff --git a/app/src/main/java/org/sopt/do_sopt_compose/ui/pages/doandroid/DoAndroid.kt b/app/src/main/java/org/sopt/do_sopt_compose/ui/pages/doandroid/DoAndroidScreen.kt similarity index 88% rename from app/src/main/java/org/sopt/do_sopt_compose/ui/pages/doandroid/DoAndroid.kt rename to app/src/main/java/org/sopt/do_sopt_compose/ui/pages/doandroid/DoAndroidScreen.kt index 193067d..941e6c6 100644 --- a/app/src/main/java/org/sopt/do_sopt_compose/ui/pages/doandroid/DoAndroid.kt +++ b/app/src/main/java/org/sopt/do_sopt_compose/ui/pages/doandroid/DoAndroidScreen.kt @@ -18,18 +18,21 @@ import androidx.compose.runtime.collectAsState import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.unit.dp +import androidx.lifecycle.viewmodel.compose.viewModel import androidx.navigation.NavController import coil.compose.rememberAsyncImagePainter import coil.request.ImageRequest +import coil.size.Size +import org.sopt.do_sopt_compose.R import org.sopt.do_sopt_compose.data.dto.User import org.sopt.do_sopt_compose.navigation.BottomNavigation @Composable -fun DoAndroid( +fun DoAndroidScreen( navController: NavController, - doAndroidViewModel: DoAndroidViewModel ) { - val usersState = doAndroidViewModel.users.collectAsState() + val viewModel: DoAndroidViewModel = viewModel() + val usersState = viewModel.users.collectAsState() Scaffold( bottomBar = { BottomNavigation(navController = navController) }, @@ -66,11 +69,12 @@ fun UserItem(user: User) { ) { // 프로필 이미지 표시 Image( - painter = //placeholder() // 로딩 중에 표시할 이미지 + painter = rememberAsyncImagePainter( ImageRequest.Builder(LocalContext.current).data(data = user.avatar) + .size(Size.ORIGINAL) .apply(block = fun ImageRequest.Builder.() { - //placeholder() // 로딩 중에 표시할 이미지 + placeholder(R.drawable.profile_background) }).build() ), contentDescription = "Profile Picture", diff --git a/app/src/main/java/org/sopt/do_sopt_compose/ui/pages/doandroid/DoAndroidSideEffect.kt b/app/src/main/java/org/sopt/do_sopt_compose/ui/pages/doandroid/DoAndroidSideEffect.kt new file mode 100644 index 0000000..695519c --- /dev/null +++ b/app/src/main/java/org/sopt/do_sopt_compose/ui/pages/doandroid/DoAndroidSideEffect.kt @@ -0,0 +1,5 @@ +package org.sopt.do_sopt_compose.ui.pages.doandroid + +sealed class DoAndroidSideEffect { + data class ToastMessage(val message: String) : DoAndroidSideEffect() +} \ No newline at end of file diff --git a/app/src/main/java/org/sopt/do_sopt_compose/ui/pages/doandroid/DoAndroidState.kt b/app/src/main/java/org/sopt/do_sopt_compose/ui/pages/doandroid/DoAndroidState.kt new file mode 100644 index 0000000..c4fec1c --- /dev/null +++ b/app/src/main/java/org/sopt/do_sopt_compose/ui/pages/doandroid/DoAndroidState.kt @@ -0,0 +1,7 @@ +package org.sopt.do_sopt_compose.ui.pages.doandroid + +import org.sopt.do_sopt_compose.ui.UiStatus + +data class DoAndroidState( + val uiStatus: UiStatus = UiStatus.Loading, +) diff --git a/app/src/main/java/org/sopt/do_sopt_compose/ui/pages/doandroid/DoAndroidViewModel.kt b/app/src/main/java/org/sopt/do_sopt_compose/ui/pages/doandroid/DoAndroidViewModel.kt index f3af224..cc7cf3d 100644 --- a/app/src/main/java/org/sopt/do_sopt_compose/ui/pages/doandroid/DoAndroidViewModel.kt +++ b/app/src/main/java/org/sopt/do_sopt_compose/ui/pages/doandroid/DoAndroidViewModel.kt @@ -5,29 +5,51 @@ import androidx.lifecycle.viewModelScope import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.launch +import org.orbitmvi.orbit.ContainerHost +import org.orbitmvi.orbit.syntax.simple.intent +import org.orbitmvi.orbit.syntax.simple.postSideEffect +import org.orbitmvi.orbit.syntax.simple.reduce +import org.orbitmvi.orbit.viewmodel.container import org.sopt.do_sopt_compose.data.PeopleRepository -import org.sopt.do_sopt_compose.data.dto.ResponsePeopleDto import org.sopt.do_sopt_compose.data.dto.User +import org.sopt.do_sopt_compose.ui.UiStatus -class DoAndroidViewModel : ViewModel() { +class DoAndroidViewModel : ContainerHost, ViewModel() { private val peopleRepository = PeopleRepository() private val _users = MutableStateFlow>(emptyList()) val users = _users.asStateFlow() + override val container = container(DoAndroidState()) init { - getPeople(1) + loadPeopleData(1) } - private fun getPeople(page: Int) { + private fun loadPeopleData(page: Int) { viewModelScope.launch { + intent { + reduce { + state.copy(uiStatus = UiStatus.Loading) + } + } try { _users.emit(peopleRepository.getUsers(page).data) - - } catch (e: Exception) { - _users.value = emptyList() - e.printStackTrace() + intent { + reduce { + state.copy(uiStatus = UiStatus.Success) + } + postSideEffect(DoAndroidSideEffect.ToastMessage("데이터 로드 성공")) + } + } catch (e: Exception) { + _users.value = emptyList() + intent { + reduce { + state.copy(uiStatus = UiStatus.Fail) + } + postSideEffect(DoAndroidSideEffect.ToastMessage("데이터 로드 실패")) + } + e.printStackTrace() + } } } -} } \ No newline at end of file diff --git a/app/src/main/res/drawable/profile_background.xml b/app/src/main/res/drawable/profile_background.xml new file mode 100644 index 0000000..e416bbc --- /dev/null +++ b/app/src/main/res/drawable/profile_background.xml @@ -0,0 +1,9 @@ + + + From f4f7dd48f71a60ce34fb72a1ecfadedc4e761f6d Mon Sep 17 00:00:00 2001 From: kangyuri1114 Date: Sun, 28 Apr 2024 20:55:26 +0900 Subject: [PATCH 5/6] =?UTF-8?q?orbit=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../do_sopt_compose/data/{ => repository}/PeopleRepository.kt | 4 +++- .../do_sopt_compose/ui/pages/doandroid/DoAndroidViewModel.kt | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) rename app/src/main/java/org/sopt/do_sopt_compose/data/{ => repository}/PeopleRepository.kt (59%) diff --git a/app/src/main/java/org/sopt/do_sopt_compose/data/PeopleRepository.kt b/app/src/main/java/org/sopt/do_sopt_compose/data/repository/PeopleRepository.kt similarity index 59% rename from app/src/main/java/org/sopt/do_sopt_compose/data/PeopleRepository.kt rename to app/src/main/java/org/sopt/do_sopt_compose/data/repository/PeopleRepository.kt index 21ea5c6..4e03709 100644 --- a/app/src/main/java/org/sopt/do_sopt_compose/data/PeopleRepository.kt +++ b/app/src/main/java/org/sopt/do_sopt_compose/data/repository/PeopleRepository.kt @@ -1,4 +1,6 @@ -package org.sopt.do_sopt_compose.data +package org.sopt.do_sopt_compose.data.repository + +import org.sopt.do_sopt_compose.data.ServicePool class PeopleRepository { diff --git a/app/src/main/java/org/sopt/do_sopt_compose/ui/pages/doandroid/DoAndroidViewModel.kt b/app/src/main/java/org/sopt/do_sopt_compose/ui/pages/doandroid/DoAndroidViewModel.kt index cc7cf3d..9dedae6 100644 --- a/app/src/main/java/org/sopt/do_sopt_compose/ui/pages/doandroid/DoAndroidViewModel.kt +++ b/app/src/main/java/org/sopt/do_sopt_compose/ui/pages/doandroid/DoAndroidViewModel.kt @@ -10,7 +10,7 @@ import org.orbitmvi.orbit.syntax.simple.intent import org.orbitmvi.orbit.syntax.simple.postSideEffect import org.orbitmvi.orbit.syntax.simple.reduce import org.orbitmvi.orbit.viewmodel.container -import org.sopt.do_sopt_compose.data.PeopleRepository +import org.sopt.do_sopt_compose.data.repository.PeopleRepository import org.sopt.do_sopt_compose.data.dto.User import org.sopt.do_sopt_compose.ui.UiStatus From d0ceba52d67ad957b6f4c3cf7e477cf781edfc9c Mon Sep 17 00:00:00 2001 From: kangyuri1114 Date: Sun, 28 Apr 2024 21:04:40 +0900 Subject: [PATCH 6/6] =?UTF-8?q?=EC=A3=BC=EC=84=9D=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/build.gradle.kts | 3 --- 1 file changed, 3 deletions(-) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index f0842aa..a18a3d9 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -92,14 +92,11 @@ dependencies { implementation ("org.jetbrains.kotlinx:kotlinx-serialization-json:1.4.1") implementation ("com.jakewharton.retrofit:retrofit2-kotlinx-serialization-converter:1.0.0") - // define a BOM and its version implementation(platform("com.squareup.okhttp3:okhttp-bom:4.10.0")) - // define any required OkHttp artifacts without version implementation("com.squareup.okhttp3:okhttp") implementation("com.squareup.okhttp3:logging-interceptor") - //OkHttp: 통신 로그 확인하기 위함 implementation ("com.squareup.okhttp3:okhttp:4.11.0") implementation ("com.squareup.okhttp3:logging-interceptor:4.10.0") implementation ("com.squareup.retrofit2:converter-gson:2.1.0")