Dim
Dim

Reputation: 4807

Running Room Persistence Library queries on coroutines GlobalScope

I read that running routines on GlobalScope is bad practice.

What am doing now is:

    class SplashScreen : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_splash_screen)


        DataBaseHelper.isDbEmpty(this, object : DataBaseHelper.OnCompleteCheckDB {
            override fun isDBEmpty(result: Boolean) {
                //handle result
            }
        })
    }
}

DatabseHelper:

class DataBaseHelper() {

companion object {
    fun isDbEmpty(context: Context, param: OnCompleteCheckDB) {

        val db = AppDatabase(context)
        GlobalScope.launch(Dispatchers.IO) {
            val count = db.movieDao().countElements() <= 0
            withContext(Dispatchers.Main) {
                param.isDBEmpty(count)
            }
        }
    }
}
}

It works, but is it bad practice? What should I change if I wish to run it on the ActivityScope?

Upvotes: 1

Views: 302

Answers (1)

Valeriy Katkov
Valeriy Katkov

Reputation: 40522

There'is lifecycleScope extension provided in lifecycle-runtime-ktx library, see Use Kotlin coroutines with Architecture components. Just add the library to your app's build.gradle

...
dependencies {
  ...
  implementation "androidx.lifecycle:lifecycle-runtime-ktx:2.2.0"
}

There's also viewModelScope available, if you're using ViewModel library. At first glance such a logic should be moved into a view model, so the query result will be retained during configuration changes. But let's use lifecycleScope since the question is about activity scope.

I've also replaced the callback by a suspend function. Coroutines are a great replacement for callbacks, so it's better to use coroutines when it's possible.

And one more thing, creating of a new AppDatabase instance multiple times doesn't look like a good idea. It's better to create it once and reuse it throughout your app. You can use Dependency Injection for that purpose, see Manage dependencies between components.

class DataBaseHelper() {
    companion object {
        suspend fun isDbEmpty(context: Context, param: OnCompleteCheckDB) = withContext(Dispatchers.IO) {
            val db = AppDatabase(context)
            db.movieDao().countElements() <= 0
        }
    }
}

class SplashScreen : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_splash_screen)

        lifecycleScope.launch {
            const dbIsEmpty = DataBaseHelper.isDbEmpty(this)
            //handle result
        }
    }
}

Upvotes: 2

Related Questions