Skip to content

Commit

Permalink
Implement data module.
Browse files Browse the repository at this point in the history
  • Loading branch information
Myungjun Hyun committed Jul 8, 2023
1 parent 41da091 commit c146e61
Show file tree
Hide file tree
Showing 20 changed files with 248 additions and 43 deletions.
2 changes: 1 addition & 1 deletion app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,4 @@
</intent-filter>
</activity>
</application>
</manifest>
</manifest>
1 change: 1 addition & 0 deletions core/data/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ plugins {
id("peonlee.android.library")
id("peonlee.android.hilt")
id("peonlee.android.repository")
kotlin("plugin.serialization") version "1.4.21"
}

android {
Expand Down
4 changes: 2 additions & 2 deletions core/data/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">

</manifest>
<uses-permission android:name="android.permission.INTERNET" />
</manifest>
21 changes: 21 additions & 0 deletions core/data/src/main/java/com/peonlee/data/Result.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package com.peonlee.data

sealed interface Result<out T> {
data class Success<T>(val data: T) : Result<T>
data class Error(val exception: Throwable) : Result<Nothing>
}

suspend fun <T : Any> setResult(response: (suspend () -> T)): Result<T> {
return try {
Result.Success(response.invoke())
} catch (e: Exception) {
Result.Error(e)
}
}

fun <T> Result<T>.handle(onSuccess: ((T) -> Unit)?, onError: ((Throwable) -> Unit)? = null) {
when (this) {
is Result.Success -> onSuccess?.invoke(data)
is Result.Error -> onError?.invoke(exception)
}
}
57 changes: 36 additions & 21 deletions core/data/src/main/java/com/peonlee/data/di/NetworkModule.kt
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import com.jakewharton.retrofit2.converter.kotlinx.serialization.asConverterFact
import com.peonlee.core.data.BuildConfig
import com.peonlee.data.di.NetworkModule.ConnectInfo.APPLICATION_JSON
import com.peonlee.data.di.NetworkModule.ConnectInfo.TIME_OUT
import com.peonlee.data.product.ProductApi
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
Expand All @@ -21,36 +22,50 @@ import javax.inject.Singleton
object NetworkModule {
@Singleton
@Provides
fun provideRetrofit(okHttpClient: OkHttpClient): Retrofit {
return Retrofit.Builder().apply {
client(okHttpClient)
baseUrl(BuildConfig.BASE_URL)
addConverterFactory(Json.asConverterFactory(APPLICATION_JSON.toMediaType()))
}.build()
fun provideJson(): Json {
return Json {
coerceInputValues = true
ignoreUnknownKeys = true
}
}

@Singleton
@Provides
fun provideRetrofit(json: Json, okHttpClient: OkHttpClient): Retrofit {
return Retrofit.Builder()
.client(okHttpClient)
.baseUrl(BuildConfig.BASE_URL)
.addConverterFactory(json.asConverterFactory(APPLICATION_JSON.toMediaType()))
.build()
}

@Singleton
@Provides
fun provideOkHttp(): OkHttpClient {
return OkHttpClient.Builder().apply {
val loggingInterceptor = HttpLoggingInterceptor()

if (BuildConfig.DEBUG) {
loggingInterceptor.level = HttpLoggingInterceptor.Level.BODY
} else {
loggingInterceptor.level = HttpLoggingInterceptor.Level.NONE
}

addInterceptor(loggingInterceptor)
connectTimeout(TIME_OUT, TimeUnit.SECONDS)
readTimeout(TIME_OUT, TimeUnit.SECONDS)
writeTimeout(TIME_OUT, TimeUnit.SECONDS)
}.build()
val loggingInterceptor = HttpLoggingInterceptor()
if (BuildConfig.DEBUG) {
loggingInterceptor.level = HttpLoggingInterceptor.Level.BODY
} else {
loggingInterceptor.level = HttpLoggingInterceptor.Level.NONE
}

return OkHttpClient.Builder()
.addInterceptor(loggingInterceptor)
.connectTimeout(TIME_OUT, TimeUnit.SECONDS)
.readTimeout(TIME_OUT, TimeUnit.SECONDS)
.writeTimeout(TIME_OUT, TimeUnit.SECONDS)
.build()
}

@Singleton
@Provides
fun provideProductApi(retrofit: Retrofit): ProductApi {
return retrofit.create(ProductApi::class.java)
}

private object ConnectInfo {
const val APPLICATION_JSON = "application/json"

const val TIME_OUT = 60L
const val TIME_OUT = 30000L
}
}
27 changes: 27 additions & 0 deletions core/data/src/main/java/com/peonlee/data/di/RepositoryModule.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package com.peonlee.data.di

import com.peonlee.data.login.LoginRepository
import com.peonlee.data.login.LoginRepositoryImpl
import com.peonlee.data.product.DefaultProductRepository
import com.peonlee.data.product.ProductRepository
import dagger.Binds
import dagger.Module
import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent
import javax.inject.Singleton

@Module
@InstallIn(SingletonComponent::class)
abstract class RepositoryModule {
@Binds
@Singleton
abstract fun bindLoginRepository(
loginRepositoryImpl: LoginRepositoryImpl
): LoginRepository

@Binds
@Singleton
abstract fun bindProductRepository(
productRepository: DefaultProductRepository
): ProductRepository
}
17 changes: 0 additions & 17 deletions core/data/src/main/java/com/peonlee/data/login/LoginModule.kt

This file was deleted.

15 changes: 15 additions & 0 deletions core/data/src/main/java/com/peonlee/data/model/Content.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package com.peonlee.data.model

import kotlinx.serialization.Serializable

@Serializable
data class Content(
val brandName: String,
val imageUrl: String,
val isPbProduct: Boolean,
val isPromotion: Boolean,
val price: Int,
val productCategoryType: String,
val productId: Int,
val productName: String
)
16 changes: 16 additions & 0 deletions core/data/src/main/java/com/peonlee/data/model/ProductDetail.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package com.peonlee.data.model

import kotlinx.serialization.Serializable

@Serializable
data class ProductDetail(
val brandName: String,
val categoryType: String,
val imageUrl: String,
val isPbProduct: Boolean,
val name: String,
val price: Int,
val productId: Int,
val promotionList: List<Promotion>,
val score: Score
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package com.peonlee.data.model

import kotlinx.serialization.Serializable

@Serializable
data class ProductSearch(
val content: List<Content>,
val lastId: Int
)
10 changes: 10 additions & 0 deletions core/data/src/main/java/com/peonlee/data/model/Promotion.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.peonlee.data.model

import kotlinx.serialization.Serializable

@Serializable
data class Promotion(
val productId: Int,
val promotionType: String,
val retailerType: String
)
12 changes: 12 additions & 0 deletions core/data/src/main/java/com/peonlee/data/model/Score.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.peonlee.data.model

import kotlinx.serialization.Serializable

@Serializable
data class Score(
val dislikeCount: Int,
val dislikeRatio: Int,
val likeCount: Int,
val likeRatio: Int,
val totalCount: Int
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package com.peonlee.data.model.request

data class ProductSearchRequest(
val keyword: String?,
val maxPrice: Int?,
val minPrice: Int?,
val offsetProductId: Int?,
val orderBy: String?,
val pageSize: Int,
val pbOnly: Boolean?,
val productCategoryTypeList: List<String>?,
val promotionRetailerList: List<String>?,
val promotionTypeList: List<String>?
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package com.peonlee.data.product

import com.peonlee.data.model.request.ProductSearchRequest
import com.peonlee.data.setResult
import javax.inject.Inject

class DefaultProductRepository @Inject constructor(
private val productApi: ProductApi
) : ProductRepository {
override suspend fun getProductDetail(productId: Int) = setResult {
productApi.getProductDetail(productId)
}

override suspend fun searchProduct(searchRequest: ProductSearchRequest) = setResult {
productApi.searchProduct(searchRequest)
}
}
20 changes: 20 additions & 0 deletions core/data/src/main/java/com/peonlee/data/product/ProductApi.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package com.peonlee.data.product

import com.peonlee.data.model.ProductDetail
import com.peonlee.data.model.ProductSearch
import com.peonlee.data.model.request.ProductSearchRequest
import retrofit2.http.GET
import retrofit2.http.Path
import retrofit2.http.Query

interface ProductApi {
@GET("v1/product/{productId}/detail")
suspend fun getProductDetail(
@Path("productId") productId: Int
): ProductDetail

@GET("v1/product/search")
suspend fun searchProduct(
@Query("query") request: ProductSearchRequest
): ProductSearch
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.peonlee.data.product

import com.peonlee.data.Result
import com.peonlee.data.model.ProductDetail
import com.peonlee.data.model.ProductSearch
import com.peonlee.data.model.request.ProductSearchRequest

interface ProductRepository {
suspend fun getProductDetail(productId: Int): Result<ProductDetail>
suspend fun searchProduct(searchRequest: ProductSearchRequest): Result<ProductSearch>
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package com.peonlee.domain.login

import com.peonlee.data.Result
import com.peonlee.data.model.ProductSearch
import com.peonlee.data.model.request.ProductSearchRequest
import com.peonlee.data.product.ProductRepository
import javax.inject.Inject

class GetHomeProductUseCase @Inject constructor(
private val productRepository: ProductRepository
) {
suspend operator fun invoke(): Result<ProductSearch> {
return productRepository.searchProduct(
ProductSearchRequest(
keyword = null,
maxPrice = null,
minPrice = null,
offsetProductId = null,
orderBy = null,
pageSize = 10,
pbOnly = null,
productCategoryTypeList = null,
promotionRetailerList = null,
promotionTypeList = null
)
)
}
}
2 changes: 2 additions & 0 deletions feature/home/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ android {
}

dependencies {
implementation(project(":core:data"))
implementation(project(":core:domain"))
implementation(project(":core:common"))
implementation(libs.google.material)
implementation(libs.androidx.recyclerview)
Expand Down
2 changes: 2 additions & 0 deletions feature/home/src/main/java/com/peonlee/home/HomeFragment.kt
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@ import com.peonlee.home.model.product.NEW_PRODUCTS
import com.peonlee.home.model.product.POP_PRODUCTS
import com.peonlee.home.model.review.RECENT_REVIEW
import com.peonlee.home.model.title.TitleUiModel
import dagger.hilt.android.AndroidEntryPoint

@AndroidEntryPoint
class HomeFragment : BaseFragment<FragmentHomeBinding>() {
override fun bindingFactory(parent: ViewGroup): FragmentHomeBinding {
return FragmentHomeBinding.inflate(layoutInflater, parent, false)
Expand Down
6 changes: 4 additions & 2 deletions feature/main/src/main/java/com/peonlee/main/MainActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,17 @@ package com.peonlee.main
import android.os.Bundle
import androidx.fragment.app.commit
import com.peonlee.core.ui.base.BaseActivity
import com.peonlee.explore.ExploreFragment
import com.peonlee.home.HomeFragment
import com.peonlee.main.databinding.ActivityMainBinding
import dagger.hilt.android.AndroidEntryPoint

@AndroidEntryPoint
class MainActivity : BaseActivity<ActivityMainBinding>() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// TODO Navigation 적용 Issue 작업 에서 수정할 예정
supportFragmentManager.commit {
add(binding.layoutFragment.id, ExploreFragment.getInstance())
add(binding.layoutFragment.id, HomeFragment.getInstance())
}
}

Expand Down

0 comments on commit c146e61

Please sign in to comment.