Fragment에서 RecyclerView의 adapter를 연동해주자.
val adapter = PlantAdapter()
binding.plantList.adapter = adapter
Plant DB에서 Data를 가져와야 하기 때문에 ViewModel과 Repository를 생성해서 Room DB에 접근한다.
// PlantRepository.kt
@Singleton
class PlantRepository @Inject constructor(private val plantDao: PlantDao) {
fun getPlants() = plantDao.getPlants()
fun getPlant(plantId: String) = plantDao.getPlant(plantId)
fun getPlantsWithGrowZoneNumber(growZoneNumber: Int) =
plantDao.getPlantsWithGrowZoneNumber(growZoneNumber)
}
Repository는 Singleton 패턴으로 생성되며, Room DB에 접근하여 가져온 데이터를 ViewModel에 넘겨준다.
Dao가 코루틴의 Flow를 반환하기 때문에 main으로부터 안전하다.
그리고, PlantDao 객체를 주입받기 위해 @Inject
어노테이션을 선언해준다.
ViewModel 의존성 주입을 위해 @HiltViewModel
어노테이션을 추가해준다.
private val growZone: MutableStateFlow<Int> = MutableStateFlow(
savedStateHandle.get(GROW_ZONE_SAVED_STATE_KEY) ?: NO_GROW_ZONE
)
val plants: LiveData<List<Plant>> = growZone.flatMapLatest { zone ->
if (zone == NO_GROW_ZONE) {
plantRepository.getPlants()
} else {
plantRepository.getPlantsWithGrowZoneNumber(zone)
}
}.asLiveData()
이 로직을 이해하기 위해선 Flow에 대해 더 공부할 필요가 있다.
flatMapLatest
: flow를 최신 데이터만을 이용해서 새로운 flow로 변환할 수 있도록 도와주는 함수 (이전 데이터가 변환되기 전에 새로운 데이터가 들어오면 이전 데이터에 대한 변환이 취소된다)
asLiveData
: Flow를 LiveData로 바꿔준다.
implementation "androidx.lifecycle:lifecycle-livedata-ktx:$rootProject.lifecycleVersion"
LiveData는 DataBinding과 결합이 좋아 flow 결과를 LiveData로 변경한다.
필터 버튼을 누르게 되면 growZone의 값이 변경된다.
plants 변수는 LiveData로 선언되어 있기 때문에,
growZone의 값 변경을 감지하여 새로운 리스트를 반환한다.
Hilt 에서 제공하는 component를 @Installin
어노테이션으로 install 한다.
@InstallIn(SingletonComponent::class)
@Module
class DatabaseModule {
...
@Provides
fun providePlantDao(appDatabase: AppDatabase): PlantDao {
return appDatabase.plantDao()
}
}
data에 imageUrl 속성이 존재한다. Glide를 통해 해당 Url에 이미지를 가져온다. 그러므로, url에 접근하기 위해서는 네트워크 통신이 가능해야 하므로 permission을 추가해준다.
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
assets 폴더에 plants.json 파일을 추가해 DB에 저장될 PlantList 데이터를 추가해준다.
추가해서 실행해보면 RecyclerView가 안나오는 경우가 있다.
그 이유는 SeedDatabaseWorker에서 json 데이터를 DB에 저장하는 작업을 단 한번만 실행해서 그렇다.
그래서, App Storage를 정리하고 다시 실행하면 잘 나온다.