Android: Download drawable via glide

1

I am trying to change my radiobutton.buttonDrawable inside my adapter. Selecting static drawables from my drawable folder works. What I now want is to download the drawables (.svg files) from my cloud-firestore-storage, convert them to a drawable and set them to the radiobutton.

My current implementation doesn't work as it just does nothing (doesn't change anything). I've already checked the urls (getItem(position).icon) and they seem correct.

Current approach

class ShopFilterItemAdapter @Inject constructor(
    // @ApplicationContext private val context: Context
) : ListAdapter<ShopFilterCategory, ShopFilterItemAdapter.ShopFilterViewHolder>(Companion) {
    private var checkedRadioButton: CompoundButton? = null
    var defaultCheckedId: Int = 0
    private lateinit var listener: OnItemSelectedListener

    companion object: DiffUtil.ItemCallback<ShopFilterCategory>() {
        override fun areItemsTheSame(oldItem: ShopFilterCategory, newItem: ShopFilterCategory): Boolean = oldItem === newItem
        override fun areContentsTheSame(oldItem: ShopFilterCategory, newItem: ShopFilterCategory): Boolean = oldItem == newItem
    }

    inner class ShopFilterViewHolder(val binding: ShopFilterListItemBinding) : RecyclerView.ViewHolder(binding.root)

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ShopFilterViewHolder {
        val layoutInflater = LayoutInflater.from(parent.context)
        val binding = ShopFilterListItemBinding.inflate(layoutInflater, parent, false)
        return ShopFilterViewHolder(binding)
    }

    override fun onBindViewHolder(holder: ShopFilterViewHolder, position: Int) {
        holder.binding.filterItem = getItem(position)

        if (checkedRadioButton == null && defaultCheckedId == position) holder.binding.rbItem.isChecked = true
        
        if (holder.binding.rbItem.isChecked) checkedRadioButton = holder.binding.rbItem

        // Trying to load the images here
        Glide.with(holder.binding.root)
            .asDrawable()
            .load(getItem(position).icon)
            .into(object : CustomTarget<Drawable>() {
                override fun onResourceReady(resource: Drawable, transition: Transition<in Drawable>?) {
                    holder.binding.rbItem.buttonDrawable = resource
                }

                override fun onLoadCleared(placeholder: Drawable?) {
                    TODO("Not yet implemented")
                }

            })

        holder.binding.executePendingBindings()
    }

EDIT

I was partially wrong, it throws an error:

java.io.IOException: java.lang.RuntimeException: setDataSourceCallback failed: status = 0x80000000
    at com.bumptech.glide.load.resource.bitmap.VideoDecoder.decode(VideoDecoder.java:185)
    at com.bumptech.glide.load.engine.DecodePath.decodeResourceWithList(DecodePath.java:92)
    at com.bumptech.glide.load.engine.DecodePath.decodeResource(DecodePath.java:70)
    at com.bumptech.glide.load.engine.DecodePath.decode(DecodePath.java:59)
    at com.bumptech.glide.load.engine.LoadPath.loadWithExceptionList(LoadPath.java:76)
    at com.bumptech.glide.load.engine.LoadPath.load(LoadPath.java:57)
    at com.bumptech.glide.load.engine.DecodeJob.runLoadPath(DecodeJob.java:524)
    at com.bumptech.glide.load.engine.DecodeJob.decodeFromFetcher(DecodeJob.java:488)
    at com.bumptech.glide.load.engine.DecodeJob.decodeFromData(DecodeJob.java:474)
    at com.bumptech.glide.load.engine.DecodeJob.decodeFromRetrievedData(DecodeJob.java:426)
    at com.bumptech.glide.load.engine.DecodeJob.onDataFetcherReady(DecodeJob.java:390)
    at com.bumptech.glide.load.engine.SourceGenerator.onDataFetcherReady(SourceGenerator.java:176)
    at com.bumptech.glide.load.engine.DataCacheGenerator.onDataReady(DataCacheGenerator.java:94)
    at com.bumptech.glide.load.model.ByteBufferFileLoader$ByteBufferFetcher.loadData(ByteBufferFileLoader.java:70)
    at com.bumptech.glide.load.engine.DataCacheGenerator.startNext(DataCacheGenerator.java:74)
    at com.bumptech.glide.load.engine.SourceGenerator.startNext(SourceGenerator.java:50)
    at com.bumptech.glide.load.engine.DecodeJob.runGenerators(DecodeJob.java:310)
    at com.bumptech.glide.load.engine.DecodeJob.runWrapped(DecodeJob.java:279)
    at com.bumptech.glide.load.engine.DecodeJob.run(DecodeJob.java:234)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
    at java.lang.Thread.run(Thread.java:919)
    at com.bumptech.glide.load.engine.executor.GlideExecutor$DefaultThreadFactory$1.run(GlideExecutor.java:393)
 Caused by: java.lang.RuntimeException: setDataSourceCallback failed: status = 0x80000000
    at android.media.MediaMetadataRetriever._setDataSource(Native Method)
    at android.media.MediaMetadataRetriever.setDataSource(MediaMetadataRetriever.java:210)
    at com.bumptech.glide.load.resource.bitmap.VideoDecoder$ByteBufferInitializer.initialize(VideoDecoder.java:316)
    at com.bumptech.glide.load.resource.bitmap.VideoDecoder$ByteBufferInitializer.initialize(VideoDecoder.java:310)
    at com.bumptech.glide.load.resource.bitmap.VideoDecoder.decode(VideoDecoder.java:173)
    at com.bumptech.glide.load.engine.DecodePath.decodeResourceWithList(DecodePath.java:92) 
    at com.bumptech.glide.load.engine.DecodePath.decodeResource(DecodePath.java:70) 
    at com.bumptech.glide.load.engine.DecodePath.decode(DecodePath.java:59) 
    at com.bumptech.glide.load.engine.LoadPath.loadWithExceptionList(LoadPath.java:76) 
    at com.bumptech.glide.load.engine.LoadPath.load(LoadPath.java:57) 
    at com.bumptech.glide.load.engine.DecodeJob.runLoadPath(DecodeJob.java:524) 
    at com.bumptech.glide.load.engine.DecodeJob.decodeFromFetcher(DecodeJob.java:488) 
    at com.bumptech.glide.load.engine.DecodeJob.decodeFromData(DecodeJob.java:474) 
    at com.bumptech.glide.load.engine.DecodeJob.decodeFromRetrievedData(DecodeJob.java:426) 
    at com.bumptech.glide.load.engine.DecodeJob.onDataFetcherReady(DecodeJob.java:390) 
    at com.bumptech.glide.load.engine.SourceGenerator.onDataFetcherReady(SourceGenerator.java:176) 
    at com.bumptech.glide.load.engine.DataCacheGenerator.onDataReady(DataCacheGenerator.java:94) 
    at com.bumptech.glide.load.model.ByteBufferFileLoader$ByteBufferFetcher.loadData(ByteBufferFileLoader.java:70) 
    at com.bumptech.glide.load.engine.DataCacheGenerator.startNext(DataCacheGenerator.java:74) 
    at com.bumptech.glide.load.engine.SourceGenerator.startNext(SourceGenerator.java:50) 
    at com.bumptech.glide.load.engine.DecodeJob.runGenerators(DecodeJob.java:310) 
    at com.bumptech.glide.load.engine.DecodeJob.runWrapped(DecodeJob.java:279) 
    at com.bumptech.glide.load.engine.DecodeJob.run(DecodeJob.java:234) 
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167) 
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641) 
    at java.lang.Thread.run(Thread.java:919) 
    at com.bumptech.glide.load.engine.executor.GlideExecutor$DefaultThreadFactory$1.run(GlideExecutor.java:393) 
android
kotlin
android-recyclerview
android-drawable
android-glide
asked on Stack Overflow Jan 5, 2021 by Andrew • edited Jan 6, 2021 by Andrew

1 Answer

0

I've managed to solve this problem, unfortunately it is not possible with glide, but with coil.

1. Add the necessary dependencies

implementation "io.coil-kt:coil-base:1.1.0" // or "io.coil-kt:coil-1.1.0" if you don't want to use dependency Injection
implementation "io.coil-kt:coil-svg:1.1.0"

2. Construct the ImageLoader Singleton and add the SVGEndoder

@Provides
@Singleton
fun provideImageLoader(@ApplicationContext context: Context) = ImageLoader.Builder(context)
    .componentRegistry { add(SvgDecoder(context)) }
    .build()

3.Build the request

fun buildRequest(context: Context, data: Any, target: RadioButton) = ImageRequest.Builder(context)
    .data(data)
    .target { drawable -> target.buttonDrawable = drawable }
    .size(64, 60) // unfortunately I was not able to get the default radiobutton.drawable size here
    .build()

4. Inside the Adapter

override fun onBindViewHolder(holder: YourHolder, position: Int) {

   val newRequest = shopFilterValidator.buildRequest(
       context = holder.binding.rbItem.context,
       data = getItem(position).icon, // here a url from firebase
       target = holder.binding.rbItem
   )

   imageLoader.enqueue(newRequest)
}

This will load the svg images as drawables and put them as the radiobutton.drawable

answered on Stack Overflow Jan 10, 2021 by Andrew

User contributions licensed under CC BY-SA 3.0