Search code examples
androidkotlinclassinitialization

Android Kotlin Class Initialization


may I ask for a moment of your time? I've been stuck for days to understand about class initialization in android studio with kotlin. I really really need basic understanding about this one. This is really different. How to properly initialize class in Android?Why I keep getting error message "lateinit property db has not been initialized"?. A little bright spot would be much appreciated. Thank you and best regards

The problem is "private lateinit var db: AppDatabase" has not been initialized. Actually what is the correct way to initialize a class in Android with klotlin?

class PinjamanSuperRepository(
    private val api: PinjamanApi,
    private val preferences: UserPreferences
) : BasePinjamanRepository(){
    private lateinit var db: AppDatabase
    private val pagingSourceFactory = { db.pinjamanAktifDao.select_all() }
    @ExperimentalPagingApi
    fun getPinjamanAktif(): Flow<PagingData<Data>> {
        return Pager(
            config = PagingConfig(
                pageSize = NETWORK_PAGE_SIZE,
                enablePlaceholders = false
            ),
            remoteMediator = PlayersRemoteMediator(
                api,
                db
            ),
            pagingSourceFactory = pagingSourceFactory
        ).flow
    }
    companion object {
        private const val NETWORK_PAGE_SIZE = 25
    }
}

This is the AppDatabase Class


   
abstract class AppDatabase : RoomDatabase() {
    abstract val pinjamanAktifDao: PinjamanAktifDao
    abstract val remoteKeysDao: RemoteKeysDao
    companion object {
        
        @Volatile
        private var instance: AppDatabase? = null
        private val LOCK = Any()

        operator fun invoke(context: Context) = instance
            ?: synchronized(LOCK) {
                instance ?: buildDatabase(
                    context
                ).also {
                    instance = it
                }
            }

        private fun buildDatabase(context: Context) =
            Room.databaseBuilder(
                context.applicationContext,
                AppDatabase::class.java,
                "app_db"
            ).fallbackToDestructiveMigration()
                .build()
    }
}

Solution

  • Simple answer make whoever is creating the PinjamanSuperRepository pass in the database.

    class PinjamanSuperRepository(
        private val api: PinjamanApi,
        private val preferences: UserPreferences,
        private val db: AppDatabase
    ) : BasePinjamanRepository()
    
    //in viewmodel or whatever has access to a context.
    
    
    val db = AppDatabase(getApplicationContext()) //however you get the AppDatabase.Companion.instance
    val repo = PinjamanSuperRepository(api,preferences,db)
    
    
    
    

    The problem your facing is you are using the RoomDatabse as a singleton which is fine, but access to it requries the user to supply a Context regardless of it already being created. PinjamanSuperRepository doesn't have access to Context so it would never be able to create/retrieve the database by itself.

    Quick but bad alternative

    fun getPinjamanAktif(context: Context): Flow<PagingData<Data>>{
        db = AppDatabase(context)
        return Pager(...)
    }