Skip to content

Commit f737786

Browse files
authored
Merge pull request #16 from birdy736/birdy736/week2
6주차 미션
2 parents bd77f9d + c2e2d11 commit f737786

File tree

15 files changed

+247
-112
lines changed

15 files changed

+247
-112
lines changed

app/build.gradle.kts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import java.util.Properties
2+
13
plugins {
24
alias(libs.plugins.android.application)
35
alias(libs.plugins.kotlin.android)
@@ -18,6 +20,15 @@ android {
1820

1921
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
2022

23+
// defaultConfig 블록 안에 추가
24+
val properties = Properties()
25+
val localPropertiesFile = rootProject.file("local.properties")
26+
if (localPropertiesFile.exists()) {
27+
properties.load(localPropertiesFile.inputStream())
28+
}
29+
val baseUrl = properties.getProperty("BASE_URL")
30+
buildConfigField("String", "BASE_URL", "\"$baseUrl\"")
31+
2132
}
2233

2334
buildTypes {
@@ -38,6 +49,7 @@ android {
3849
}
3950
buildFeatures {
4051
compose = true
52+
buildConfig = true
4153
}
4254
}
4355

@@ -68,10 +80,16 @@ dependencies {
6880

6981
// Coroutines
7082
implementation(libs.kotlinx.coroutines.android)
83+
implementation(libs.retrofit2.retrofit)
7184

7285
testImplementation(libs.junit)
7386
androidTestImplementation(libs.androidx.junit)
7487
androidTestImplementation(libs.androidx.espresso.core)
7588
debugImplementation(libs.androidx.compose.ui.tooling)
7689
debugImplementation(libs.androidx.compose.ui.test.manifest)
90+
91+
//retro & okhttp
92+
implementation(libs.retrofit.converter.gson)
93+
implementation(libs.okhttp)
94+
implementation(libs.okhttp.logging.interceptor)
7795
}

app/src/main/java/com/example/kuit6_android_api/MainActivity.kt

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,22 @@
11
package com.example.kuit6_android_api
22

33
import android.Manifest
4+
import android.annotation.SuppressLint
45
import android.content.pm.PackageManager
56
import android.os.Build
67
import android.os.Bundle
78
import android.widget.Toast
89
import androidx.activity.ComponentActivity
910
import androidx.activity.compose.setContent
1011
import androidx.activity.result.contract.ActivityResultContracts
12+
import androidx.compose.foundation.background
1113
import androidx.compose.foundation.layout.fillMaxSize
1214
import androidx.compose.material3.MaterialTheme
15+
import androidx.compose.material3.Scaffold
16+
import androidx.compose.material3.SnackbarHost
17+
import androidx.compose.material3.SnackbarHostState
1318
import androidx.compose.material3.Surface
19+
import androidx.compose.runtime.remember
1420
import androidx.compose.ui.Modifier
1521
import androidx.core.content.ContextCompat
1622
import androidx.navigation.compose.rememberNavController
@@ -32,6 +38,7 @@ class MainActivity : ComponentActivity() {
3238
}
3339
}
3440

41+
@SuppressLint("UnusedMaterial3ScaffoldPaddingParameter")
3542
override fun onCreate(savedInstanceState: Bundle?) {
3643
super.onCreate(savedInstanceState)
3744

@@ -40,15 +47,23 @@ class MainActivity : ComponentActivity() {
4047

4148
setContent {
4249
KUIT6_Android_APITheme {
43-
Surface(
44-
modifier = Modifier.fillMaxSize(),
45-
color = MaterialTheme.colorScheme.background
50+
51+
val snackBarState = remember { SnackbarHostState() }
52+
53+
Scaffold(
54+
modifier = Modifier
55+
.fillMaxSize()
56+
.background(MaterialTheme.colorScheme.background),
57+
snackbarHost = {
58+
SnackbarHost(snackBarState)
59+
}
4660
) {
4761
val navController = rememberNavController()
4862

4963
NavGraph(
5064
navController = navController,
51-
startDestination = PostListRoute
65+
startDestination = PostListRoute,
66+
snackBarState = snackBarState
5267
)
5368
}
5469
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
package com.example.kuit6_android_api.data.api
2+
3+
import com.example.kuit6_android_api.data.model.response.BaseResponse
4+
import com.example.kuit6_android_api.data.model.response.PostResponse
5+
import com.example.kuit6_android_api.data.model.request.PostCreateRequest
6+
import okhttp3.MultipartBody
7+
import retrofit2.http.*
8+
9+
interface ApiService {
10+
@GET("/api/posts")
11+
suspend fun getPosts(): BaseResponse<List<PostResponse>>
12+
13+
@POST("/api/posts")
14+
suspend fun createPost(
15+
@Query("author") author: String = "시헌",
16+
@Body request: PostCreateRequest
17+
): BaseResponse<PostResponse>
18+
19+
@DELETE("/api/posts/{id}")
20+
suspend fun deletePost(
21+
@Path("id") id: Long
22+
): BaseResponse<Unit> // data에 빈 객체 반환
23+
24+
@GET("/api/posts/{id}")
25+
suspend fun getPostDetail(
26+
@Path("id") id: Long
27+
): BaseResponse<PostResponse>
28+
29+
// 업데이트 요청
30+
@PUT("/api/posts/{id}")
31+
suspend fun updatePost(
32+
@Path("id") id: Long,
33+
@Body request: PostCreateRequest // 수정된 내용 전달
34+
): BaseResponse<PostResponse>
35+
36+
@Multipart
37+
@POST("/api/images/upload")
38+
suspend fun uploadImage(
39+
@Part file: MultipartBody.Part
40+
): BaseResponse<Map<String, String>>
41+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
package com.example.kuit6_android_api.data.api
2+
3+
import com.example.kuit6_android_api.BuildConfig
4+
import okhttp3.OkHttpClient
5+
import okhttp3.logging.HttpLoggingInterceptor
6+
import retrofit2.Retrofit
7+
import retrofit2.converter.gson.GsonConverterFactory
8+
import java.util.concurrent.TimeUnit
9+
10+
object RetrofitClient {
11+
12+
private val loggingInterceptor = HttpLoggingInterceptor().apply {
13+
level = HttpLoggingInterceptor.Level.BODY
14+
}
15+
16+
private val okHttpClient = OkHttpClient.Builder()
17+
.addInterceptor(loggingInterceptor)
18+
.connectTimeout(30, TimeUnit.SECONDS)
19+
.readTimeout(30, TimeUnit.SECONDS)
20+
.writeTimeout(30, TimeUnit.SECONDS)
21+
.build()
22+
23+
private val retrofit: Retrofit = Retrofit.Builder()
24+
.baseUrl(BuildConfig.BASE_URL)
25+
.client(okHttpClient)
26+
.addConverterFactory(GsonConverterFactory.create())
27+
.build()
28+
29+
val apiService: ApiService = retrofit.create(ApiService::class.java)
30+
}

app/src/main/java/com/example/kuit6_android_api/data/model/Post.kt

Lines changed: 0 additions & 17 deletions
This file was deleted.
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
package com.example.kuit6_android_api.data.model.request
2+
3+
import kotlinx.serialization.SerialName
4+
5+
data class PostCreateRequest(
6+
@SerialName(value = "title") val title:String,
7+
@SerialName(value = "content") val content:String,
8+
@SerialName(value = "imageUrl") val imageUrl:String?
9+
)
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
package com.example.kuit6_android_api.data.model.response
2+
3+
import kotlinx.serialization.SerialName
4+
5+
data class AuthorResponse (
6+
@SerialName(value = "id") val id : Long,
7+
@SerialName(value = "username") val username: String,
8+
@SerialName(value = "profileImageUrl") val profileImageUrl:String?
9+
)
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
package com.example.kuit6_android_api.data.model.response
2+
3+
import kotlinx.serialization.SerialName
4+
5+
data class BaseResponse<T>(
6+
@SerialName(value = "success") val success : Boolean,
7+
@SerialName(value = "message") val message : String?,
8+
@SerialName(value = "data") val data: T?,
9+
@SerialName(value = "timestamp") val timestamp: String
10+
)
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package com.example.kuit6_android_api.data.model.response
2+
3+
import kotlinx.serialization.SerialName
4+
5+
data class PostResponse(
6+
@SerialName(value = "id") val id : Long,
7+
@SerialName(value = "title") val title:String,
8+
@SerialName(value = "content") val content : String,
9+
@SerialName(value = "imageUrl") val imageUrl:String?,
10+
@SerialName(value = "author") val author: AuthorResponse,
11+
@SerialName(value = "createdAt") val createdAt:String,
12+
@SerialName(value = "updatedAt") val updatedAt:String
13+
)

app/src/main/java/com/example/kuit6_android_api/ui/navigation/NavGraph.kt

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
package com.example.kuit6_android_api.ui.navigation
22

3+
import androidx.compose.material3.SnackbarHostState
34
import androidx.compose.runtime.Composable
5+
import androidx.compose.runtime.MutableState
46
import androidx.navigation.NavHostController
57
import androidx.navigation.compose.NavHost
68
import androidx.navigation.compose.composable
@@ -13,7 +15,8 @@ import com.example.kuit6_android_api.ui.post.screen.PostListScreen
1315
@Composable
1416
fun NavGraph(
1517
navController: NavHostController,
16-
startDestination: Any = PostListRoute
18+
startDestination: Any = PostListRoute,
19+
snackBarState: SnackbarHostState
1720
) {
1821
NavHost(
1922
navController = navController,
@@ -40,7 +43,8 @@ fun NavGraph(
4043
},
4144
onEditClick = { postId ->
4245
navController.navigate(PostEditRoute(postId))
43-
}
46+
},
47+
snackBarState = snackBarState
4448
)
4549
}
4650

@@ -51,7 +55,8 @@ fun NavGraph(
5155
},
5256
onPostCreated = {
5357
navController.popBackStack()
54-
}
58+
},
59+
snackBarState = snackBarState
5560
)
5661
}
5762

@@ -65,7 +70,8 @@ fun NavGraph(
6570
},
6671
onPostUpdated = {
6772
navController.popBackStack()
68-
}
73+
},
74+
snackBarState = snackBarState
6975
)
7076
}
7177
}

0 commit comments

Comments
 (0)