diff --git a/app/build.gradle b/app/build.gradle index 7400c6d..786bd26 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -6,6 +6,9 @@ plugins { id 'kotlin-parcelize' } +Properties properties = new Properties() +properties.load(project.rootProject.file('local.properties').newDataInputStream()) + android { namespace 'org.sopt.carrot' compileSdk 34 @@ -17,6 +20,8 @@ android { versionCode 1 versionName "1.0" + buildConfigField "String", "BASE_URL", properties["base.url"] + testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" } @@ -36,6 +41,7 @@ android { buildFeatures { viewBinding true dataBinding true + buildConfig true } } diff --git a/app/src/main/java/org/sopt/carrot/CarrotApp.kt b/app/src/main/java/org/sopt/carrot/CarrotApp.kt index 22e7f32..995f914 100644 --- a/app/src/main/java/org/sopt/carrot/CarrotApp.kt +++ b/app/src/main/java/org/sopt/carrot/CarrotApp.kt @@ -2,6 +2,9 @@ package org.sopt.carrot import android.app.Application import androidx.appcompat.app.AppCompatDelegate +import org.sopt.carrot.data.api.RetrofitServicePool +import org.sopt.carrot.data.datasource.remote.NeighborhoodLifeRemoteDatasource +import org.sopt.carrot.data.repo.NeighborhoodLifeRepository import timber.log.Timber class CarrotApp : Application() { @@ -17,4 +20,21 @@ class CarrotApp : Application() { AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO) } + companion object { + private lateinit var neighborhoodLifeRepository: NeighborhoodLifeRepository + + @Synchronized + fun getNeighborhoodLifeRepositoryInstance(): NeighborhoodLifeRepository { + if (!::neighborhoodLifeRepository.isInitialized) { + try { + neighborhoodLifeRepository = NeighborhoodLifeRepository( + NeighborhoodLifeRemoteDatasource(RetrofitServicePool.carrotService) + ) + } catch (e: ExceptionInInitializerError) { + e.printStackTrace() + } + } + return neighborhoodLifeRepository + } + } } \ No newline at end of file diff --git a/app/src/main/java/org/sopt/carrot/data/api/NeighborhoodLifeService.kt b/app/src/main/java/org/sopt/carrot/data/api/CarrotService.kt similarity index 74% rename from app/src/main/java/org/sopt/carrot/data/api/NeighborhoodLifeService.kt rename to app/src/main/java/org/sopt/carrot/data/api/CarrotService.kt index 59f8f55..07af9b1 100644 --- a/app/src/main/java/org/sopt/carrot/data/api/NeighborhoodLifeService.kt +++ b/app/src/main/java/org/sopt/carrot/data/api/CarrotService.kt @@ -4,9 +4,12 @@ import org.sopt.carrot.data.model.neighborhoodlife.LivesResponse import retrofit2.http.GET import retrofit2.http.Query -interface NeighborhoodLifeService { +interface CarrotService { @GET("api/lives") fun getLives( @Query("category") category: String ): LivesResponse + + @GET("api/lives") + suspend fun getLives(): LivesResponse } \ No newline at end of file diff --git a/app/src/main/java/org/sopt/carrot/data/api/RetrofitManager.kt b/app/src/main/java/org/sopt/carrot/data/api/RetrofitManager.kt new file mode 100644 index 0000000..17077c3 --- /dev/null +++ b/app/src/main/java/org/sopt/carrot/data/api/RetrofitManager.kt @@ -0,0 +1,33 @@ +package org.sopt.carrot.data.api + +import com.jakewharton.retrofit2.converter.kotlinx.serialization.asConverterFactory +import kotlinx.serialization.json.Json +import okhttp3.MediaType.Companion.toMediaType +import okhttp3.OkHttpClient +import okhttp3.logging.HttpLoggingInterceptor +import org.sopt.carrot.BuildConfig +import retrofit2.Retrofit + +object RetrofitManager { + private const val BASE_URL = BuildConfig.BASE_URL + + private val httpLoggingInterceptor = HttpLoggingInterceptor() + .setLevel(HttpLoggingInterceptor.Level.BODY) + + private val okHttpClient = OkHttpClient.Builder() + .addInterceptor(httpLoggingInterceptor) + .build() + + val retrofit: Retrofit = + Retrofit.Builder() + .baseUrl(BASE_URL) + .client(okHttpClient) + .addConverterFactory(Json.asConverterFactory("application/json".toMediaType())) + .build() + + inline fun create(): T = retrofit.create(T::class.java) +} + +object RetrofitServicePool { + val carrotService = RetrofitManager.create() +} \ No newline at end of file diff --git a/app/src/main/java/org/sopt/carrot/data/datasource/remote/NeighborhoodLifeRemoteDatasource.kt b/app/src/main/java/org/sopt/carrot/data/datasource/remote/NeighborhoodLifeRemoteDatasource.kt index 50a73f9..b78b0bf 100644 --- a/app/src/main/java/org/sopt/carrot/data/datasource/remote/NeighborhoodLifeRemoteDatasource.kt +++ b/app/src/main/java/org/sopt/carrot/data/datasource/remote/NeighborhoodLifeRemoteDatasource.kt @@ -1,14 +1,19 @@ package org.sopt.carrot.data.datasource.remote -import org.sopt.carrot.data.api.NeighborhoodLifeService +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.async +import kotlinx.coroutines.withContext +import org.sopt.carrot.data.api.CarrotService import org.sopt.carrot.data.model.neighborhoodlife.LivesDataResponse -import org.sopt.carrot.data.model.neighborhoodlife.LivesResponse -import retrofit2.Response class NeighborhoodLifeRemoteDatasource( - private val neighborhoodLifeService: NeighborhoodLifeService + private val carrotService: CarrotService ) { - suspend fun getLives(category: String): List { - return neighborhoodLifeService.getLives(category).data + suspend fun getLives(): List { + return withContext(Dispatchers.IO) { + async { + carrotService.getLives().data + }.await() + } } } \ No newline at end of file diff --git a/app/src/main/java/org/sopt/carrot/data/repo/NeighborhoodLifeRepository.kt b/app/src/main/java/org/sopt/carrot/data/repo/NeighborhoodLifeRepository.kt index 7afc7b9..ff6350e 100644 --- a/app/src/main/java/org/sopt/carrot/data/repo/NeighborhoodLifeRepository.kt +++ b/app/src/main/java/org/sopt/carrot/data/repo/NeighborhoodLifeRepository.kt @@ -4,13 +4,12 @@ import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext import org.sopt.carrot.data.datasource.remote.NeighborhoodLifeRemoteDatasource import org.sopt.carrot.data.model.neighborhoodlife.LivesDataResponse -import kotlin.coroutines.coroutineContext class NeighborhoodLifeRepository( private val neighborhoodLifeRemoteDatasource: NeighborhoodLifeRemoteDatasource ) { - suspend fun getLives(category: String): List = + suspend fun getLives(): List = withContext(Dispatchers.IO) { - neighborhoodLifeRemoteDatasource.getLives(category) + neighborhoodLifeRemoteDatasource.getLives() } } \ No newline at end of file diff --git a/app/src/main/java/org/sopt/carrot/presentation/neighborhoodlife/NeighborhoodLifeFragment.kt b/app/src/main/java/org/sopt/carrot/presentation/neighborhoodlife/NeighborhoodLifeFragment.kt index 250e72b..b966ef8 100644 --- a/app/src/main/java/org/sopt/carrot/presentation/neighborhoodlife/NeighborhoodLifeFragment.kt +++ b/app/src/main/java/org/sopt/carrot/presentation/neighborhoodlife/NeighborhoodLifeFragment.kt @@ -4,7 +4,9 @@ import android.content.Intent import android.os.Bundle import android.view.View import androidx.fragment.app.Fragment -import androidx.fragment.app.activityViewModels +import androidx.recyclerview.widget.DividerItemDecoration +import androidx.recyclerview.widget.RecyclerView.VERTICAL +import org.sopt.carrot.CarrotApp import org.sopt.carrot.R import org.sopt.carrot.core.ui.base.BindingFragment import org.sopt.carrot.core.ui.fragment.snackBar @@ -18,7 +20,7 @@ import org.sopt.carrot.presentation.profile.ProfileActivity class NeighborhoodLifeFragment : BindingFragment(R.layout.fragment_neighborhood_life) { - private val neighborhoodViewModel: NeighborhoodViewModel by activityViewModels() + private lateinit var neighborhoodViewModel: NeighborhoodViewModel private lateinit var neighborhoodLifeAdapter: NeighborhoodLifeAdapter private lateinit var carouselTextAdapter: CarouselTextAdapter @@ -26,6 +28,7 @@ class NeighborhoodLifeFragment : override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) + initNeighborhoodLifeViewModel() initCarouselTextDummyAdapter() initCarouselTagDummyAdapter() initNeighborhoodLifeAdapter() @@ -34,6 +37,12 @@ class NeighborhoodLifeFragment : observeData() } + private fun initNeighborhoodLifeViewModel() { + neighborhoodViewModel = NeighborhoodLifeViewModelProvider( + CarrotApp.getNeighborhoodLifeRepositoryInstance() + ).create(NeighborhoodViewModel::class.java) + } + private fun initLives() { neighborhoodViewModel.getLives() } @@ -59,6 +68,7 @@ class NeighborhoodLifeFragment : private fun initNeighborhoodLifeAdapter() { neighborhoodLifeAdapter = NeighborhoodLifeAdapter() binding.rcvContents.adapter = neighborhoodLifeAdapter + binding.rcvContents.addItemDecoration(DividerItemDecoration(requireContext(), VERTICAL)) } private fun observeData() { diff --git a/app/src/main/java/org/sopt/carrot/presentation/neighborhoodlife/NeighborhoodLifeViewModelProvider.kt b/app/src/main/java/org/sopt/carrot/presentation/neighborhoodlife/NeighborhoodLifeViewModelProvider.kt new file mode 100644 index 0000000..b771daa --- /dev/null +++ b/app/src/main/java/org/sopt/carrot/presentation/neighborhoodlife/NeighborhoodLifeViewModelProvider.kt @@ -0,0 +1,14 @@ +package org.sopt.carrot.presentation.neighborhoodlife + +import androidx.lifecycle.ViewModel +import androidx.lifecycle.ViewModelProvider +import org.sopt.carrot.data.repo.NeighborhoodLifeRepository + +class NeighborhoodLifeViewModelProvider( + private val neighborhoodLifeRepository: NeighborhoodLifeRepository +) : ViewModelProvider.Factory { + override fun create(modelClass: Class): T { + return modelClass.getConstructor(NeighborhoodLifeRepository::class.java) + .newInstance(neighborhoodLifeRepository) + } +} \ No newline at end of file diff --git a/app/src/main/java/org/sopt/carrot/presentation/neighborhoodlife/NeighborhoodViewModel.kt b/app/src/main/java/org/sopt/carrot/presentation/neighborhoodlife/NeighborhoodViewModel.kt index e20edde..100cb00 100644 --- a/app/src/main/java/org/sopt/carrot/presentation/neighborhoodlife/NeighborhoodViewModel.kt +++ b/app/src/main/java/org/sopt/carrot/presentation/neighborhoodlife/NeighborhoodViewModel.kt @@ -14,10 +14,10 @@ class NeighborhoodViewModel( private val _livesList = MutableLiveData>() val livesList: LiveData> get() = _livesList - fun getLives(category: String = "") { + fun getLives() { viewModelScope.launch { kotlin.runCatching { - neighborhoodLifeRepository.getLives(category) + neighborhoodLifeRepository.getLives() }.onSuccess { _livesList.value = it }.onFailure {