Skip to content

Instantly share code, notes, and snippets.

@drochetti
Created March 27, 2021 05:54
Show Gist options
  • Save drochetti/68c604364edbeb84158ff428bb49f93f to your computer and use it in GitHub Desktop.
Save drochetti/68c604364edbeb84158ff428bb49f93f to your computer and use it in GitHub Desktop.
Amplify + Glide integration for image rendering
import android.content.Context
import com.amplifyframework.core.Amplify
import com.amplifyframework.storage.StorageAccessLevel
import com.amplifyframework.storage.operation.StorageDownloadFileOperation
import com.amplifyframework.storage.options.StorageDownloadFileOptions
import com.bumptech.glide.Glide
import com.bumptech.glide.Priority
import com.bumptech.glide.Registry
import com.bumptech.glide.annotation.GlideModule
import com.bumptech.glide.load.DataSource
import com.bumptech.glide.load.Options
import com.bumptech.glide.load.data.DataFetcher
import com.bumptech.glide.load.model.ModelLoader
import com.bumptech.glide.load.model.ModelLoader.LoadData
import com.bumptech.glide.load.model.ModelLoaderFactory
import com.bumptech.glide.load.model.MultiModelLoaderFactory
import com.bumptech.glide.module.AppGlideModule
import com.bumptech.glide.signature.ObjectKey
import java.io.File
import java.io.FileNotFoundException
import java.io.InputStream
import java.util.*
data class AmplifyImageModel(
val context: Context,
val key: String,
val accessLevel: StorageAccessLevel = StorageAccessLevel.PUBLIC
) {
val cacheKey: String
get() = "${accessLevel.name.toLowerCase(Locale.getDefault())}_${key}"
}
class AmplifyStorageModelLoader : ModelLoader<AmplifyImageModel, InputStream> {
override fun buildLoadData(
model: AmplifyImageModel,
width: Int,
height: Int,
options: Options
): LoadData<InputStream> {
return LoadData(ObjectKey(model.cacheKey), AmplifyStorageDataFetcher(model))
}
override fun handles(model: AmplifyImageModel): Boolean {
return true
}
}
class AmplifyStorageDataFetcher(
private val model: AmplifyImageModel
) : DataFetcher<InputStream> {
private var downloadOperation: StorageDownloadFileOperation<*>? = null
private val tempFile: File
get() = File(model.context.cacheDir, model.cacheKey)
override fun loadData(priority: Priority, callback: DataFetcher.DataCallback<in InputStream>) {
val options = StorageDownloadFileOptions
.builder()
.accessLevel(model.accessLevel)
.build()
val file = tempFile
file.delete()
if (!file.createNewFile()) {
callback.onLoadFailed(
FileNotFoundException("Could not create temp file for image loading: ${file.path}")
)
return
}
this.downloadOperation = Amplify.Storage.downloadFile(
model.key,
tempFile,
options,
{ callback.onDataReady(it.file.inputStream()) },
{ callback.onLoadFailed(it) }
)
}
override fun cleanup() {
if (tempFile.exists()) {
tempFile.delete()
}
}
override fun cancel() {
downloadOperation?.cancel()
}
override fun getDataClass(): Class<InputStream> {
return InputStream::class.java
}
override fun getDataSource(): DataSource {
return DataSource.REMOTE
}
}
object AmplifyGlideModelLoaderFactory : ModelLoaderFactory<AmplifyImageModel, InputStream> {
override fun build(multiFactory: MultiModelLoaderFactory): ModelLoader<AmplifyImageModel, InputStream> {
return AmplifyStorageModelLoader()
}
override fun teardown() {
// do nothing
}
}
@GlideModule
class AmplifyGlideModule : AppGlideModule() {
override fun registerComponents(context: Context, glide: Glide, registry: Registry) {
registry.append(
AmplifyImageModel::class.java,
InputStream::class.java,
AmplifyGlideModelLoaderFactory
)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment