refactor: switch to coil for image loading (#388)

This commit is contained in:
Jarne Demeulemeester 2023-05-29 16:44:03 +02:00 committed by GitHub
parent 3fc72bf8b3
commit 1399c77b5d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 44 additions and 75 deletions

View file

@ -108,7 +108,8 @@ dependencies {
implementation(libs.androidx.room.ktx)
implementation(libs.androidx.swiperefreshlayout)
implementation(libs.androidx.work)
implementation(libs.glide)
implementation(libs.coil)
implementation(libs.coil.svg)
implementation(libs.hilt.android)
kapt(libs.hilt.compiler)
implementation(libs.jellyfin.core)

View file

@ -4,13 +4,18 @@ import android.app.Application
import androidx.appcompat.app.AppCompatDelegate
import androidx.hilt.work.HiltWorkerFactory
import androidx.work.Configuration
import coil.ImageLoader
import coil.ImageLoaderFactory
import coil.decode.SvgDecoder
import coil.disk.DiskCache
import coil.request.CachePolicy
import com.google.android.material.color.DynamicColors
import dagger.hilt.android.HiltAndroidApp
import javax.inject.Inject
import timber.log.Timber
@HiltAndroidApp
class BaseApplication : Application(), Configuration.Provider {
class BaseApplication : Application(), Configuration.Provider, ImageLoaderFactory {
@Inject
lateinit var appPreferences: AppPreferences
@ -37,4 +42,19 @@ class BaseApplication : Application(), Configuration.Provider {
if (appPreferences.dynamicColors) DynamicColors.applyToActivitiesIfAvailable(this)
}
override fun newImageLoader(): ImageLoader {
return ImageLoader.Builder(this)
.components {
add(SvgDecoder.Factory())
}
.diskCachePolicy(if (appPreferences.imageCache) CachePolicy.ENABLED else CachePolicy.DISABLED)
.diskCache {
DiskCache.Builder()
.directory(this.cacheDir.resolve("image_cache"))
.maxSizeBytes(appPreferences.imageCacheSize * 1024L * 1024)
.build()
}
.build()
}
}

View file

@ -5,8 +5,7 @@ import android.widget.ImageView
import androidx.annotation.DrawableRes
import androidx.databinding.BindingAdapter
import androidx.recyclerview.widget.RecyclerView
import com.bumptech.glide.Glide
import com.bumptech.glide.load.resource.drawable.DrawableTransitionOptions
import coil.load
import dev.jdtech.jellyfin.adapters.HomeEpisodeListAdapter
import dev.jdtech.jellyfin.adapters.ServerGridAdapter
import dev.jdtech.jellyfin.adapters.ViewItemListAdapter
@ -49,7 +48,6 @@ fun bindItemImage(imageView: ImageView, item: BaseItemDto) {
fun bindItemImage(imageView: ImageView, item: FindroidItem) {
val itemId = when (item) {
is FindroidEpisode -> item.seriesId
// is JellyfinSeasonItem && item.imageTags.isNullOrEmpty() -> item.seriesId
else -> item.id
}
@ -111,18 +109,15 @@ fun bindUserImage(imageView: ImageView, user: User) {
private fun ImageView.loadImage(
url: String,
@DrawableRes placeholderId: Int = CoreR.color.neutral_800,
@DrawableRes errorPlaceHolderId: Int? = null
@DrawableRes placeholderId: Int = CoreR.color.neutral_800
): View {
val api = JellyfinApi.getInstance(context.applicationContext)
Glide
.with(context)
.load("${api.api.baseUrl}$url")
.transition(DrawableTransitionOptions.withCrossFade())
.placeholder(placeholderId)
.error(errorPlaceHolderId)
.into(this)
this.load("${api.api.baseUrl}$url") {
crossfade(true)
placeholder(placeholderId)
error(placeholderId)
}
return this
}

View file

@ -1,12 +1,13 @@
package dev.jdtech.jellyfin.utils
import android.graphics.Bitmap
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import androidx.media3.common.Player
import androidx.media3.ui.TimeBar
import com.bumptech.glide.Glide
import com.bumptech.glide.load.resource.bitmap.RoundedCorners
import coil.load
import coil.transform.RoundedCornersTransformation
import dev.jdtech.jellyfin.utils.bif.BifData
import dev.jdtech.jellyfin.utils.bif.BifUtil
import kotlinx.coroutines.flow.StateFlow
@ -19,7 +20,8 @@ class PreviewScrubListener(
private val currentTrickPlay: StateFlow<BifData?>
) : TimeBar.OnScrubListener {
private val roundedCorners = RoundedCorners(10)
private val roundedCorners = RoundedCornersTransformation(10f)
private var currentBitMap: Bitmap? = null
override fun onScrubStart(timeBar: TimeBar, position: Long) {
Timber.d("Scrubbing started at $position")
@ -54,10 +56,12 @@ class PreviewScrubListener(
scrubbingPreview.x = layoutX
Glide.with(scrubbingPreview)
.load(image)
.transform(roundedCorners)
.into(scrubbingPreview)
if (currentBitMap != image) {
scrubbingPreview.load(image) {
transformations(roundedCorners)
}
currentBitMap = image
}
}
override fun onScrubStop(timeBar: TimeBar, position: Long, canceled: Boolean) {

View file

@ -62,8 +62,6 @@ dependencies {
kapt(libs.androidx.room.compiler)
implementation(libs.androidx.room.ktx)
implementation(libs.androidx.work)
implementation(libs.glide)
kapt(libs.glide.compiler)
implementation(libs.hilt.android)
kapt(libs.hilt.compiler)
implementation(libs.jellyfin.core)

View file

@ -1,49 +0,0 @@
package dev.jdtech.jellyfin.di
import android.content.Context
import androidx.preference.PreferenceManager
import com.bumptech.glide.GlideBuilder
import com.bumptech.glide.annotation.GlideModule
import com.bumptech.glide.load.engine.DiskCacheStrategy.NONE
import com.bumptech.glide.load.engine.DiskCacheStrategy.RESOURCE
import com.bumptech.glide.load.engine.cache.InternalCacheDiskCacheFactory
import com.bumptech.glide.module.AppGlideModule
import com.bumptech.glide.request.RequestOptions
import dev.jdtech.jellyfin.AppPreferences
import kotlinx.coroutines.MainScope
import kotlinx.coroutines.launch
import timber.log.Timber
@GlideModule
class GlideModule : AppGlideModule() {
override fun applyOptions(context: Context, builder: GlideBuilder) {
val preferences = AppPreferences(PreferenceManager.getDefaultSharedPreferences(context))
val use = preferences.imageCache
if (use) {
val sizeMb = preferences.imageCacheSize
val sizeB = 1024L * 1024 * sizeMb
Timber.d("Setting image cache to use $sizeMb MB of disk space")
builder.setDiskCache(InternalCacheDiskCacheFactory(context, sizeB))
builder.caching(enabled = true)
} else {
builder.caching(enabled = false)
Timber.d("Image cache disabled. Clearing all persisted data.")
MainScope().launch {
GlideApp.getPhotoCacheDir(context)?.also {
if (it.exists()) it.deleteRecursively()
}
}
}
}
private fun GlideBuilder.caching(enabled: Boolean) {
setDefaultRequestOptions(
RequestOptions().diskCacheStrategy(
if (enabled) RESOURCE else NONE
)
)
}
}

View file

@ -17,7 +17,7 @@ androidx-recyclerview-selection = "1.1.0"
androidx-room = "2.5.1"
androidx-swiperefreshlayout = "1.1.0"
androidx-work = "2.8.1"
glide = "4.15.1"
coil = "2.4.0"
hilt = "2.46.1"
jellyfin = "1.4.2"
kotlin = "1.8.21"
@ -55,8 +55,8 @@ androidx-room-compiler = { module = "androidx.room:room-compiler", version.ref =
androidx-room-ktx = { module = "androidx.room:room-ktx", version.ref = "androidx-room" }
androidx-swiperefreshlayout = { module = "androidx.swiperefreshlayout:swiperefreshlayout", version.ref = "androidx-swiperefreshlayout" }
androidx-work = { module = "androidx.work:work-runtime-ktx", version.ref = "androidx-work" }
glide = { module = "com.github.bumptech.glide:glide", version.ref = "glide" }
glide-compiler = { module = "com.github.bumptech.glide:compiler", version.ref = "glide" }
coil = { module = "io.coil-kt:coil", version.ref = "coil" }
coil-svg = { module = "io.coil-kt:coil-svg", version.ref = "coil" }
hilt-android = { module = "com.google.dagger:hilt-android", version.ref = "hilt" }
hilt-compiler = { module = "com.google.dagger:hilt-compiler", version.ref = "hilt" }
jellyfin-core = { module = "org.jellyfin.sdk:jellyfin-core", version.ref = "jellyfin" }