Issue
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)
Solution
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 By - Andrew
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.