Skip to content

Commit

Permalink
set data module and add app preferences with protobuf [FoKE-Developer…
Browse files Browse the repository at this point in the history
…s#22]

- data 모듈 구성
- protobuf datastore 추가
- TODO: 추후, data 모듈을 특성에 따라 여러 모듈로 나누는 방향 검토
  • Loading branch information
DokySp committed Sep 24, 2024
1 parent 3f128c5 commit 12e7c4a
Show file tree
Hide file tree
Showing 15 changed files with 351 additions and 15 deletions.
46 changes: 40 additions & 6 deletions data/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,19 +1,53 @@
plugins {
alias(libs.plugins.android.library)
alias(libs.plugins.jetbrains.kotlin.android)
alias(libs.plugins.protobuf)
}

android {
namespace = "${libs.versions.id.get()}.data"
}

protobuf {
protoc {
artifact = libs.versions.protoc.get()
}
generateProtoTasks {
all().forEach { task ->
task.builtins {
create("java") {
option("lite")
}
}
}
}
}

dependencies {
implementation(libs.androidx.core.ktx)
implementation(libs.androidx.appcompat)
implementation(libs.material)
testImplementation(libs.junit)
androidTestImplementation(libs.androidx.junit)
androidTestImplementation(libs.androidx.espresso.core)
// work manager
implementation(libs.androidx.work.runtime.ktx)
implementation(libs.androidx.hilt.work)

// room
kapt(libs.androidx.room.compiler)
implementation(libs.androidx.room.runtime)
implementation(libs.androidx.room.ktx)

// retrofit
implementation(libs.ok.http.base)
implementation(libs.retrofit.base)
implementation(libs.retrofit.gson)
implementation(libs.google.gson)

// serialization
implementation(libs.serialization)
implementation(libs.serialization.converter)

// proto datastore
implementation(libs.datastore)
implementation(libs.datastore.preferences)
implementation(libs.datastore.preferences.core)
implementation(libs.protobuf.javalite)

// module dependency
implementation(project(":domain"))
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
package com.foke.together.data.datasource.local.database

class AppDatabase {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
package com.foke.together.data.datasource.local.database

class DBConstants {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
package com.foke.together.data.datasource.local.database.di

object DatabaseModule {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package com.foke.together.data.datasource.local.datastore

import androidx.datastore.core.Serializer
import com.foke.together.AppPreferences
import com.foke.together.util.AppLog
import java.io.InputStream
import java.io.OutputStream
import javax.inject.Inject

class AppPreferencesSerializer @Inject constructor(): Serializer<AppPreferences> {
override val defaultValue: AppPreferences
get() = AppPreferences.newBuilder().run {
// Add proto datastore default value here.
// You need to check default value of each types from link below
// https://protobuf.dev/programming-guides/proto3/
// ex> isDebugMode = true
build()
}

override suspend fun readFrom(input: InputStream): AppPreferences {
return try {
AppPreferences.parseFrom(input)
} catch (exception: Exception) {
// IOException | InvalidProtocolBufferException
AppLog.e(TAG, "readFrom", exception.toString())
defaultValue
}
}

override suspend fun writeTo(t: AppPreferences, output: OutputStream) =
t.writeTo(output)

companion object {
private val TAG = AppPreferencesSerializer::class.java.simpleName

}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package com.foke.together.data.datasource.local.datastore.di

import android.content.Context
import androidx.datastore.core.DataStore
import androidx.datastore.core.DataStoreFactory
import androidx.datastore.dataStoreFile
import com.foke.together.AppPreferences
import com.foke.together.data.datasource.local.datastore.AppPreferencesSerializer
import com.foke.together.util.di.ApplicationScope
import com.foke.together.util.di.IODispatcher
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.android.components.ViewModelComponent
import dagger.hilt.android.qualifiers.ApplicationContext
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.CoroutineScope

@Module
@InstallIn(ViewModelComponent::class)
object PreferencesModule {
@Provides
fun provideAppPreferencesDataStore(
@ApplicationContext context: Context,
@ApplicationScope scope: CoroutineScope,
@IODispatcher ioDispatcher: CoroutineDispatcher,
appPreferencesSerializer: AppPreferencesSerializer
): DataStore<AppPreferences> = DataStoreFactory.create(
serializer = appPreferencesSerializer,
scope = CoroutineScope(scope.coroutineContext + ioDispatcher),
produceFile = { context.dataStoreFile("app_preferences.pb") }
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
package com.foke.together.data.datasource.remote;

public class RemoteDataSource {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package com.foke.together.data.repository

import androidx.datastore.core.DataStore
import com.foke.together.AppPreferences
import com.foke.together.domain.output.AppPreferenceRepository
import com.foke.together.domain.output.SampleData
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.map
import javax.inject.Inject

// TODO: datasource -> local / remote 기준으로 module 구분하는게 어떨지?
class AppPreferencesRepositoryImpl @Inject constructor(
private val appPreferences: DataStore<AppPreferences>
): AppPreferenceRepository {
private val appPreferencesFlow: Flow<AppPreferences> = appPreferences.data

override fun getSampleData(): Flow<SampleData> =
appPreferencesFlow.map {
SampleData(it.sampleId, it.sampleTitle, it.sampleDescription)
}

override suspend fun setSampleData(data: SampleData) {
appPreferences.updateData {
it.toBuilder()
.setSampleId(data.id)
.setSampleTitle(data.title)
.setSampleDescription(data.description)
.build()
}
}

override suspend fun clearAll() {
appPreferences.updateData {
it.toBuilder().clear().build()
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package com.foke.together.data.repository.di

import com.foke.together.data.repository.AppPreferencesRepositoryImpl
import com.foke.together.domain.output.AppPreferenceRepository
import dagger.Binds
import dagger.Module
import dagger.hilt.InstallIn
import dagger.hilt.android.components.ViewModelComponent

@Module
@InstallIn(ViewModelComponent::class)
abstract class RepositoryModule {
@Binds
abstract fun bindAppPreferenceRepository(appPreferenceRepository: AppPreferencesRepositoryImpl): AppPreferenceRepository
}
18 changes: 18 additions & 0 deletions data/src/main/proto/app_preferences.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
syntax = "proto3";

option java_package = "com.foke.together";
option java_multiple_files = true;

message AppPreferences {
// Check the guide of Protocol Buffers before create new field.
// https://protobuf.dev/programming-guides/proto3/

// Notes for set a new Field number
// * This number cannot be changed once your message type is in use.
// * The field number of 19,000 to 19,999 was reserved by Protocol Buffers implementation.
// * Max size of field number is 536870911

string sample_id = 999997;
string sample_title = 999998;
string sample_description = 999999;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package com.foke.together.domain.output

import kotlinx.coroutines.flow.Flow

interface AppPreferenceRepository {
fun getSampleData(): Flow<SampleData>
suspend fun setSampleData(data: SampleData)
suspend fun clearAll()
}

data class SampleData (
val id: String,
val title: String,
val description: String,
)
73 changes: 65 additions & 8 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -26,17 +26,42 @@ lifecycleRuntimeKtx = "2.8.6"
activityCompose = "1.9.2"
composeBom = "2024.09.02"
material = "1.12.0"
navigationCompose = "2.8.1"

# hilt -----------
hilt = "2.49"
androidx-hilt-compiler = "1.2.0"
androidx-hilt-navigation-compose = "1.2.0"
androidx-hilt-work = "1.2.0"

# room -----------
room = "2.6.1"

# work manager ---
work-runtime-ktx = "2.9.1"

# retrofit -------
okhttp = "4.10.0"
retrofit = "2.9.0"
gson = "2.10.1"

# serialization --
serialization-json = "1.5.1"
serialization-converter = "1.0.0"

# proto datastore
datastore = "1.1.1"
protobuf = "3.23.2"
protobuf-plugin = "0.9.4"
protoc = "com.google.protobuf:protoc:4.28.2"

# lifecycle-viewmodel-ktx
lifecycle-viewmodel-ktx = "2.8.6"

# test -----------
junit = "4.13.2"
junitVersion = "1.2.1"
espressoCore = "3.6.1"
navigationCompose = "2.7.6"



Expand All @@ -58,17 +83,46 @@ androidx-ui-test-junit4 = { group = "androidx.compose.ui", name = "ui-test-junit
androidx-material3 = { group = "androidx.compose.material3", name = "material3" }
androidx-navigation-compose = { group = "androidx.navigation", name = "navigation-compose", version.ref = "navigationCompose" }

# test -----------
junit = { group = "junit", name = "junit", version.ref = "junit" }
androidx-junit = { group = "androidx.test.ext", name = "junit", version.ref = "junitVersion" }
androidx-espresso-core = { group = "androidx.test.espresso", name = "espresso-core", version.ref = "espressoCore" }
androidx-appcompat = { group = "androidx.appcompat", name = "appcompat", version.ref = "appcompat" }

# hilt -----------
hilt = { group = "com.google.dagger", name = "hilt-android", version.ref = "hilt" }
hilt-compiler = { group = "com.google.dagger", name = "hilt-android-compiler", version.ref = "hilt" }
androidx-hilt-compiler = { group = "androidx.hilt", name = "hilt-compiler", version.ref = "androidx-hilt-compiler" }
androidx-hilt-navigation-compose = { group = "androidx.hilt", name = "hilt-navigation-compose", version.ref = "androidx-hilt-navigation-compose" }
androidx-hilt-work = { group = "androidx.hilt", name = "hilt-work", version.ref = "androidx-hilt-work" }

# work manager ---
androidx-work-runtime-ktx = { group = "androidx.work", name = "work-runtime-ktx", version.ref = "work-runtime-ktx" }

# room -----------
androidx-room-runtime = { group = "androidx.room", name = "room-runtime", version.ref = "room" }
androidx-room-ktx = { group = "androidx.room", name = "room-ktx", version.ref = "room" }
androidx-room-compiler = { group = "androidx.room", name = "room-compiler", version.ref = "room" }

# retrofit -------
ok-http-base = { group = "com.squareup.okhttp3", name = "okhttp", version.ref = "okhttp" }
retrofit_base = { group = "com.squareup.retrofit2", name = "converter-gson", version.ref = "retrofit" }
retrofit_gson = { group = "com.squareup.retrofit2", name = "retrofit", version.ref = "retrofit" }
google_gson = { group = "com.google.code.gson", name = "gson", version.ref = "gson" }

# serialization --
serialization = { group = "org.jetbrains.kotlinx", name = "kotlinx-serialization-json", version.ref = "serialization-json" }
serialization_converter = { group = "com.jakewharton.retrofit", name = "retrofit2-kotlinx-serialization-converter", version.ref = "serialization-converter" }

# proto datastore
datastore = { group = "androidx.datastore", name = "datastore", version.ref = "datastore" }
datastore_preferences = { group = "androidx.datastore", name = "datastore-preferences", version.ref = "datastore" }
datastore_preferences_core = { group = "androidx.datastore", name = "datastore-preferences-core", version.ref = "datastore" }
protobuf_javalite = { group = "com.google.protobuf", name = "protobuf-javalite", version.ref = "protobuf" }

# lifecycle viewmodel
androidx-lifecycle-viewmodel = { group = "androidx.lifecycle", name = "lifecycle-viewmodel-ktx", version.ref = "lifecycle-viewmodel-ktx" }


# test -----------
junit = { group = "junit", name = "junit", version.ref = "junit" }
androidx-junit = { group = "androidx.test.ext", name = "junit", version.ref = "junitVersion" }
androidx-espresso-core = { group = "androidx.test.espresso", name = "espresso-core", version.ref = "espressoCore" }
androidx-appcompat = { group = "androidx.appcompat", name = "appcompat", version.ref = "appcompat" }



Expand All @@ -79,4 +133,7 @@ android-library = { id = "com.android.library", version.ref = "agp" }
kotlin-kapt = { id = "org.jetbrains.kotlin.kapt", version.ref = "kotlin-kapt"}

# hilt -----------
hilt = { id = "com.google.dagger.hilt.android", version.ref = "hilt"}
hilt = { id = "com.google.dagger.hilt.android", version.ref = "hilt"}

# proto datastore
protobuf = { id = "com.google.protobuf", version.ref = "protobuf-plugin" }
10 changes: 9 additions & 1 deletion presenter/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -24,16 +24,24 @@ android {
dependencies {
implementation(libs.androidx.core.ktx)
implementation(libs.androidx.lifecycle.runtime.ktx)

// android ui
implementation(libs.androidx.activity.compose)
implementation(platform(libs.androidx.compose.bom))
implementation(libs.androidx.ui)
implementation(libs.androidx.ui.graphics)
implementation(libs.androidx.ui.tooling.preview)
implementation(libs.androidx.material3)
implementation(libs.androidx.hilt.compiler)
implementation(libs.androidx.hilt.navigation.compose)

// navigation
implementation(libs.androidx.hilt.navigation.compose)
implementation(libs.androidx.navigation.compose)

// view model
implementation(libs.androidx.lifecycle.viewmodel)

// test
testImplementation(libs.junit)
androidTestImplementation(libs.androidx.junit)
androidTestImplementation(libs.androidx.espresso.core)
Expand Down
Loading

0 comments on commit 12e7c4a

Please sign in to comment.