Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add suspend room db accessor #115

Open
LouisCAD opened this issue Aug 24, 2018 · 4 comments
Open

Add suspend room db accessor #115

LouisCAD opened this issue Aug 24, 2018 · 4 comments

Comments

@LouisCAD
Copy link
Owner

No description provided.

@LouisCAD LouisCAD added New feature up for grabs Available for external contributions. Add a comment if you want to work on a PR. labels Aug 24, 2018
@LouisCAD
Copy link
Owner Author

Example of home grown technique:

private val someDb by lazy { roomDb<SomethingDatabase>("something") }
suspend fun someDb() = withContext(ioDispatcher) { someDb }

With such a function:

suspend operator fun <T : RoomDatabase> Lazy<T>.invoke(): T = if (isInitialized()) value
else withContext(ioDispatcher) { value }

this can be reduced to this:

val someDb = lazy { roomDb<SomethingDatabase>("some") } // Client code

@LouisCAD
Copy link
Owner Author

The suspend operator fun invoke should be put in a sub-package named lazydb so it looks obvious from the imports

@LouisCAD
Copy link
Owner Author

LouisCAD commented Nov 20, 2018

Here's an implementation of this issue in the sample sources:

inline fun <reified DB : RoomDatabase> roomDataBase(
name: String,
crossinline config: DbConfig<DB> = {}
): LazyRoom<DB> =
LazyRoom(lazy { roomDb(name, config) })
class LazyRoom<T : RoomDatabase> @PublishedApi internal constructor(private val lazyDb: Lazy<T>) {
suspend operator fun invoke(): T = with(lazyDb) {
if (isInitialized()) value else withContext(Dispatchers.IO) { value }
}
}

@LouisCAD
Copy link
Owner Author

The SuspenLazy class allows more than just usage for Room:

open class SuspendLazy<out T>(
private val dispatcher: CoroutineDispatcher = Dispatchers.Default,
initializer: () -> T
) {
private val lazyValue = lazy(initializer)
suspend operator fun invoke(): T = with(lazyValue) {
if (isInitialized()) value else withContext(dispatcher) { value }
}
}

Here's how it can be used for Room:

inline fun <reified DB : RoomDatabase> roomDataBase(
name: String,
crossinline config: DbConfig<DB> = {}
): SuspendLazy<DB> = SuspendLazy(Dispatchers.IO) { roomDb(name, config) }

it can also be used for SharedPreferences:

class GamePreferences private constructor() : Preferences("gameState") {
companion object : SuspendLazy<GamePreferences>(Dispatchers.IO, ::GamePreferences)

@LouisCAD LouisCAD removed the up for grabs Available for external contributions. Add a comment if you want to work on a PR. label Nov 25, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant