Giter Club home page Giter Club logo

Comments (19)

elye avatar elye commented on September 13, 2024 6

Just to check if this is already supported? In glide, I can do as below (placeholder -> initial-fast-load -> full-load)

image

With codes as below

val requestOption = RequestOptions()
        .placeholder(R.drawable.placeholder).centerCrop()
Glide.with(this).load(fullImageUrl)
       .transition(DrawableTransitionOptions.withCrossFade())
       .thumbnail(Glide.with(this)
            .load(fastLoadUrl)
            .apply(requestOption))
       .apply(requestOption)
       .into(my_image_view)

Refer to this article https://medium.com/mobile-app-development-publication/glide-image-loader-the-basic-798db220bb44

Hopes Coil can do the same.

from coil.

kasem-sm avatar kasem-sm commented on September 13, 2024 2

can anyone suggest any workaround for the coil to achieve the same?

Here you go. It is used by me in my prod app and no issues/complaints till now. If anyone finds a better solution, please let me know.

from coil.

0n4li avatar 0n4li commented on September 13, 2024 2

can anyone suggest any workaround for the coil to achieve the same?

Slight changes to kasem-sm's reply:

fun ImageView.loadWithQuality(
    highQuality: String,
    lowQuality: String,
    placeholderRes: Int? = null,
    errorRes: Int? = null
) {

    placeholderRes?.let {
        setImageResource(placeholderRes)
    }

    var isHighQualityLoaded = false

    class CallbackImageViewTarget(val callback: () -> Boolean) : ImageViewTarget(this) {
        override fun onSuccess(result: Drawable) {
            if (callback()) {
                super.onSuccess(result)
            }
        }
    }

    val lowQualityRequest = ImageRequest.Builder(context).apply {
        data(lowQuality)
        target(CallbackImageViewTarget(
            callback = {
                return@CallbackImageViewTarget !isHighQualityLoaded
            }
        ))
    }.build()

    val lowQualityLoader = context.imageLoader.enqueue(lowQualityRequest)

    val highQualityRequest = ImageRequest.Builder(context).apply {
        data(highQuality)
        errorRes?.let { error(errorRes) }
        target(CallbackImageViewTarget(
            callback = {
                isHighQualityLoaded = true
                if (!lowQualityLoader.isDisposed) {
                    lowQualityLoader.dispose()
                }
                return@CallbackImageViewTarget true
            }
        ))
    }.build()

    context.imageLoader.enqueue(highQualityRequest)

}

from coil.

0n4li avatar 0n4li commented on September 13, 2024 2

Probably the below code works better. Need to test:

fun ImageView.loadWithQuality(
    highQuality: String,
    lowQuality: String,
    placeholderRes: Int? = null,
    errorRes: Int? = null
) {
    load(lowQuality) {
        placeholderRes?.let { placeholder(placeholderRes) }
        listener(onSuccess = { _, _ ->
            load(highQuality) {
                placeholder(drawable) // If there was a way to not clear existing image before loading, this would not be required
                errorRes?.let { error(errorRes) }
            }
        })
    }
}

from coil.

colinrtwhite avatar colinrtwhite commented on September 13, 2024

Thanks! I've thought about adding a placeholder(data) method, however have shied away from it so far. Adding it would create more work on the main thread, which could reduce performance. Also, it could result in some unexpected behaviour where you expect something to be in the memory cache and it isn't.

from coil.

lfielke avatar lfielke commented on September 13, 2024

Good points. It sounds like what I'm talking about isn't really a "placeholder", because Coil assumes that placeholders are available straight away, synchronously on the main thread. Have I understood that correctly?

Thinking about this overnight, could you do two loads one-after the other, the first one loading the thumbnail URL but specifying a read only cache policies?

Something like this:

imageView.load(thumbUrl) {
  diskCachePolicy = READ_ONLY
  networkCachePolicy = DISABLED
  placeholder = R.drawable.image_placeholder
  crossfade(true) // crossfade from image_placeholder to thumbnail if it loads from disk
}
imageView.load(fullSizeUrl) {
  crossfade(true) // crossfade from thumbnail to full image
}

These requests could technically race, which could be a problem in general with this approach. I'm not sure what the desired behaviour even is when you have two loads for the same target. In this example, you want the first load to proceed, but only until the second load completes. But loading into a RecyclerView you want the opposite, where the first load should be cancelled as soon as the view is reused and the second load starts.

from coil.

colinrtwhite avatar colinrtwhite commented on September 13, 2024

Ah I see what you mean. This would add a decent chunk of complexity to RealImageLoader so I'm not sure I'd want to add this in. However, you could create the same effect with get:

coroutineScope.launch(Dispatchers.Main.immediate) {
    val thumb = async { imageLoader.get(thumbUrl) }
    val fullSize = async { imageLoader.get(fullSizeUrl) }
    fullSize.invokeOnCompletion { thumb.cancel() }
    
    // There's probably a better way to do this.
    val thumbDrawable = try {
        thumb.await()
    } catch (e: CancellationException) {
        null
    }
    imageView.setDrawable(thumbDrawable)

    val fullSizeDrawable = fullSize.await()
    imageView.setDrawable(fullSizeDrawable)
}

Replace imageLoader with Coil if you use the singleton. To figure out whether or not to crossfade, you can add a Request.Listener and check the returned DataSource in onSuccess.

Disclaimer: the above code is completely untested and unoptimized.

from coil.

Pitel avatar Pitel commented on September 13, 2024

I'd like something similar. I'd like to load image from cache (almost) immediately, but also check the network in the background for change.

Our image server supports ETag, and 304 Unchaged response. But because the URL is still the same, Coil will store the image in memory, and never asks the network again, so the user does not see the updated image. So I have the memory cache disabled, but then, when scrolling long list up and down, the images are always blank first and load later, which is distracting.

from coil.

kasem-sm avatar kasem-sm commented on September 13, 2024

Still waiting for this :(

from coil.

frel avatar frel commented on September 13, 2024

I would also like to see this feature implemented. I've created a library named AirBrush that uses this feature in Glide, but I'm planning to support Coil due to JetPack Compose. I can hack around it and use TransitionDrawable but I would prefer to use the API :)

from coil.

Leeonardoo avatar Leeonardoo commented on September 13, 2024

This feature is the only thing keeping me using Glide for bigger projects. Would love to see a way to do that using Coil

from coil.

rakshitsoni02 avatar rakshitsoni02 commented on September 13, 2024

can anyone suggest any workaround for the coil to achieve the same?

from coil.

kasem-sm avatar kasem-sm commented on September 13, 2024

@0n4li Hey, thanks for improving that code 😊

from coil.

sechiyo97 avatar sechiyo97 commented on September 13, 2024

Is there any plan to support this feature?

This feature is the only thing keeping me using Glide for bigger projects. Would love to see a way to do that using Coil

same Here :'(

from coil.

rizwan3742 avatar rizwan3742 commented on September 13, 2024

any update on this ??

from coil.

khygu0919 avatar khygu0919 commented on September 13, 2024
        val requestBuilder = Glide.with(context)
            .asDrawable()
            .sizeMultiplier(0.5f)
        GlideImage(
            model = contentUri,
            contentDescription = null,
            modifier = Modifier.fillMaxSize(),
            contentScale = ContentScale.Crop,
        ){
            it
                .override(this.maxWidth.value.dpToPx(), this.maxHeight.value.dpToPx())
                .thumbnail(requestBuilder)
        }

does coil support thumbnail size loading as glide does? when i load lot of image in grid in compose, it seems to be delayed compared to scroll action while loading image.

from coil.

timkabot avatar timkabot commented on September 13, 2024

Any updates on this?
Interrested in the way to implement this behaviour with AsyncImage in compose)

from coil.

devazimjon avatar devazimjon commented on September 13, 2024

I tried this and it worked for me in compose:

AsyncImage(
        model = "high resolution image",
        placeholder = rememberAsyncImagePainter("low resolution image"),
        contentScale = ContentScale.Crop,
        contentDescription = "",
        )

from coil.

dazza5000 avatar dazza5000 commented on September 13, 2024

Anyone have an idea on how to do this? Maybe we can throw up an MR to add this support.

from coil.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.