SunFlower Dao관련 에러 잡자!!

disun.sj·2023년 6월 18일
0

Sunflower Copy

목록 보기
3/4

카피 프로젝트 링크

우선 에러부터 잡자!

  • cannot be provided without an @Provides-annotated method. 에러가 발생
  • Sunflower 프로젝트를 보다보니 module을 안만들어 준게 의심이 된다 만들어주자

DatabaseModule

@InstallIn(SingletonComponent::class)
@Module
class DatabaseModule {
    @Singleton
    @Provides
    fun provideAppDatabase(@ApplicationContext context: Context):AppDatabase{
        return AppDatabase.getInstance(context)
    }

    @Provides
    fun providePlantDao(appDatabase: AppDatabase): PlantDao{
        return appDatabase.plantDao()
    }
}
  • AppDatabase class가 필요하다. 만들어주자
  • AppDatabase 작성중 @Database(entities = [GardenPlanting::class. Plant::class], version = 1, exportSchema = false)를 선언하려는데 GardenPlanting이 필요하여 먼저 만들어 주도록 한다

GardenPlanting

@Entity(tableName = "garden_plantings", foreignKeys = [ForeignKey(entity = Plant::class, parentColumns = ["id"], childColumns = ["plant_id"])], indices = [Index("plant_id")])
data class GardenPlanting(
    @ColumnInfo(name = "plant_id") val plantId : String,
    @ColumnInfo(name = "plant_data") val plantDate : Calendar = Calendar.getInstance(),
    @ColumnInfo(name = "last_watering_date") val lastWateringDate : Calendar = Calendar.getInstance()
){
    @PrimaryKey(autoGenerate = true)
    @ColumnInfo(name = "id") var gardenPlantingId:Long = 0
}
  • @Entity, @ColumnInfo, @PrimaryKey 모두 room에 속해있는 기능이다. 따라서 room을 정리할 때 이부분에 대해서는 정리할 예정이다

  • 다시 AppDatabase로 돌아와 이어서 작성해주자

AppDatabase

@Database(entities = [GardenPlanting::class, Plant::class], version = 1, exportSchema = false)
abstract class AppDatabase : RoomDatabase() {
    abstract fun plantDao(): PlantDao
    companion object{
        @Volatile private var instance : AppDatabase? = null

        fun getInstance(context: Context): AppDatabase{
            return instance?: synchronized(this){
                instance ?: buildDatabase(context).also{ instance = it }
            }
        }

        private fun buildDatabase(context: Context):AppDatabase{
            return Room.databaseBuilder(context, AppDatabase::class.java, DATABASE_NAME)
                .addCallback(
                    object : Callback(){
                        override fun onCreate(db: SupportSQLiteDatabase) {
                            super.onCreate(db)
                            val request = OneTimeWorkRequestBuilder<SeedDatabaseWorker>().setInputData(
                                workDataOf(KEY_FILENAME to PLANT_DATA_FILENAME)).build()
                            WorkManager.getInstance(context).enqueue(request)
                        }
                    }
                ).build()
        }
    }
}
  • @Volatile을 사용중인데 잘 몰라서 찾아보니 메인메모리에 변수를 저장시키는 Annotation이라고 하는데, 어디에 사용하는지 아직 잘 모르겠다
  • const val DATABASE_NAME = "sunflower-db" 을 사용 하고 있기에 Sunflower를 따라서 Constants를 만들어주고 const를 추가해준뒤 돌아오자

Constants

const val DATABASE_NAME = "sunflower-db"
const val PLANT_DATA_FILENAME = "plants.json"
  • OneTimeWorkRequestBuilder, WorkManager는 모두 work gradle을 사용하고 있다.
  • "androidx.work:work-testing", "androidx.work:work-runtime-ktx" gradle을 추가해주자(version "2.8.0" 사용)
  • compileSdk 버전 31 이상이 필요하다고 한다
  • WorkManager에 대해 찾아보니 백그라운드에서 작업을 처리하는 방법이라고 한다. 생각보다 내용이 방대해서 별도로 정리하는게 좋아보인다
  • SeedDatbaseWorker 만들어주자

SeedDatabaseWorker

class SeedDatabaseWorker(context: Context, workerParams: WorkerParameters):CoroutineWorker(context, workerParams) {
    companion object{
        private const val TAG = "SeedDatabaseWorker"
        const val KEY_FILENAME = "PLANT_DATA_FILENAME"
    }
    override suspend fun doWork(): Result = withContext(Dispatchers.IO){
        try {
            val filename = inputData.getString(KEY_FILENAME)
            if(filename != null){
                applicationContext.assets.open(filename).use { inputStream ->
                    JsonReader(inputStream.reader()).use { jsonReader ->
                        val plantType = object : TypeToken<List<Plant>>() {}.type
                        val plantList: List<Plant> = Gson().fromJson(jsonReader, plantType)

                        val database = AppDatabase.getInstance(applicationContext)
                        database.plantDao().insertAll(plantList)

                        Result.success()
                    }
                }
            }else{
                Log.e(TAG, "Error seeding database - no valid filename")
                Result.failure()
            }
        }catch (ex:Exception){
            Log.e(TAG, "Error seeding database", ex)
            Result.failure()
        }
    }
}
  • "com.google.code.gson" gradle 선언 해준다(version "2.10.1" 사용)
  • database에서 plant 정보를 가져오는 기능으로 보인다
  • module 관련해서 정리를 해놓고 빌드를 돌려보니 아래의 에러가 발생하며 annotation과 관련된 에러가 발생하였다
FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':app:checkDebugDuplicateClasses'.
> A failure occurred while executing com.android.build.gradle.internal.tasks.CheckDuplicatesRunnable
  • 추가적으로 아래 문구가 붙은 에러들이 잔뜩 생겼다
found in modules annotations-12.0 (com.intellij:annotations:12.0) and annotations-13.0 (org.jetbrains:annotations:13.0)
  • 이 부분에 대해 알아보니 configurations { implementation.exclude group: 'org.jetbrains', module: 'annotations' }를 붙이면 해결이 된다고 한다
  • 난 groovy가 아닌 kotlin을 사용중이기 때문에 이에 맞춰서 변경해준 코드를 gradle에 추가해줬다
    configurations {
        implementation {
            exclude(group = "org.jetbrains", module = "annotations")
        }
    }
  • 다행히 에러는 잡혔지만 Sunflower에는 이런 부분이 없다
  • 의심가는 부분은 libs.versions.toml에서 jetbrain_android = {id="org.jetbrains.kotlin.android", version.ref = "jetbrain_android" } 부분과 kotlin_bom = {group = "org.jetbrains.kotlin", name = "kotlin-bom", version.ref = "kotlin_bom" }이다
  • 각각 plugin, library의 org.jetbrains 관련된 부분으로 Sunflower와 다른 부분이다

의심부는 찾았으니 해결은 다음에 이어서 하도록 하자

0개의 댓글