CREATE VIEW bandWithAlbum AS
SELECT
band.id,
band.name,
album.*
FROM band
JOIN album ON band.id = album.band_id;
bandsOrderedByName:
SELECT *
FROM bandWithAlbum
ORDER BY name DESC;
bandsOrderedByAge:
SELECT *
FROM bandWithAlbum
ORDER BY age;
SQLDelight は、BandWithAlbum タイプを生成します。
続いて、ページネーションの例。
count:
SELECT count(*)
FROM bandWithAlbum;
paged:
SELECT *
FROM bandWithAlbum
LIMIT ?
OFFSET ?;
enum class Sort { NAME, AGE }
fun bandsSorted(by: Sort): Flow<List<BandWithAlbum>> = when (by) {
NAME -> db.bandsOrderedByName()
AGE -> db.bandsOrderedByAge()
}.asFlow().mapToList()
// To load an image into an ImageView, use the load extension function.
imageView.load("https://www.example.com/image.jpg")
// Coil supports urls, uris, resources, drawables, bitmaps, files, and more.
imageView.load(R.drawable.image)
imageView.load(File("/path/to/image.jpg"))
imageView.load(Uri.parse("content://com.android.externalstorage/image.jpg"))
// Requests can be configured with an optional trailing lambda.
imageView.load("https://www.example.com/image.jpg") {
crossfade(true)
placeholder(R.drawable.image)
transformations(CircleCropTransformation())
}
// Custom targets can be created using lambda syntax (onStart and onError are optional).
Coil.load(context, "https://www.example.com/image.jpg") {
target { drawable ->
// Handle the successful result.
}
}
// To get an image imperatively, use the get suspend function.
val drawable = Coil.get("https://www.example.com/image.jpg")
@Provides, the most common construct for configuring a binding, serves three functions:
1. Declare which type (possibly qualified) is being provided — this is the return type
2. Declare dependencies — these are the method parameters
3. Provide an implementation for exactly how the instance is provided — this is the method body
While the first two functions are unique and critical to every @Provides method, the third can often be tedious and repetitive. So, whenever there is a @Provides whose implementation is simple and common enough to be inferred by Dagger, it makes sense to just declare that as a method without a body (an abstract method) and have Dagger apply the behavior.
But, if we were to just say that abstract @Provides methods should be treated as we do for @Binds methods, the specification of @Provides would basically be two specifications with a bunch of conditional logic. For example, a @Provides method can have any number of parameters of any type, but a @Binds method can only have a single parameter whose type is assignable to the return type. Separating those specifications makes it easier to reason about correctness because the annotation determines the constraints.
- kotlin
- coroutine
- single activity
- architecture component
- navigation component + fragment
- presentetion layer(per page) = fragment + view model
- reactive ui = live data + data binding
- data layer = repositpory + local(room) + remote
- datalayer one shot operations(no listener or data streams)
suspend fun showSomeData() = coroutineScope {
val data = async(Dispatchers.IO) { // <- extension on current scope
// ... load some UI data for the Main thread ...
}
withContext(Dispatchers.Main) {
doSomeWork()
val result = data.await()
display(result)
}
}