Image loading for Android backed by Kotlin Coroutines.

Overview

Coil

An image loading library for Android backed by Kotlin Coroutines. Coil is:

  • Fast: Coil performs a number of optimizations including memory and disk caching, downsampling the image in memory, re-using bitmaps, automatically pausing/cancelling requests, and more.
  • Lightweight: Coil adds ~2000 methods to your APK (for apps that already use OkHttp and Coroutines), which is comparable to Picasso and significantly less than Glide and Fresco.
  • Easy to use: Coil's API leverages Kotlin's language features for simplicity and minimal boilerplate.
  • Modern: Coil is Kotlin-first and uses modern libraries including Coroutines, OkHttp, Okio, and AndroidX Lifecycles.

Coil is an acronym for: Coroutine Image Loader.

Made with ❤️ at Instacart. Translations: 한국어, 中文

Download

Coil is available on mavenCentral().

implementation("io.coil-kt:coil:1.1.1")

Quick Start

To load an image into an ImageView, use the load extension function:

// URL
imageView.load("https://www.example.com/image.jpg")

// Resource
imageView.load(R.drawable.image)

// File
imageView.load(File("/path/to/image.jpg"))

// And more...

Requests can be configured with an optional trailing lambda:

imageView.load("https://www.example.com/image.jpg") {
    crossfade(true)
    placeholder(R.drawable.image)
    transformations(CircleCropTransformation())
}

Image Loaders

imageView.load uses the singleton ImageLoader to enqueue an ImageRequest. The singleton ImageLoader can be accessed using an extension function:

val imageLoader = context.imageLoader

Optionally, you can create your own ImageLoader instance(s) and inject them with dependency injection:

val imageLoader = ImageLoader(context)

If you do not want the singleton ImageLoader, depend on io.coil-kt:coil-base.

Requests

To load an image into a custom target, enqueue an ImageRequest:

val request = ImageRequest.Builder(context)
    .data("https://www.example.com/image.jpg")
    .target { drawable ->
        // Handle the result.
    }
    .build()
val disposable = imageLoader.enqueue(request)

To load an image imperatively, execute an ImageRequest:

val request = ImageRequest.Builder(context)
    .data("https://www.example.com/image.jpg")
    .build()
val drawable = imageLoader.execute(request).drawable

Check out Coil's full documentation here.

Requirements

R8 / Proguard

Coil is fully compatible with R8 out of the box and doesn't require adding any extra rules.

If you use Proguard, you may need to add rules for Coroutines, OkHttp and Okio.

License

Copyright 2021 Coil Contributors

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

   https://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
Comments
  • Dropped frames while scrolling in list with multiple spans

    Dropped frames while scrolling in list with multiple spans

    I'm observing some pretty hefty main thread blockage using the latest Coil version (0.11.0) and older ones too. I just migrated from Glide on this app (I've used Coil before in other projects but never in a RV adapter) and everything was smooth until I tried scrolling on the RV. Anyway, tested with both ixel 3 and OnePlus 7T Pro so clearly not an hardware bottleneck.

    My setup is a 5 span GridLayoutManager vertical scrolling. One device has +300 pictures, the other has ~50, so doesn't seem related to the amount of pictures. What I observe is when I start scrolling when Coil is decoding the URIs and starting to display the thumbnails something seems to block the main thread and the whole thing gets blocked and it seems to suspend the entire operation. Sometimes I have to wait 3-4 seconds for it to finish whatever it seems to be doing and it then resumes.

    In the screenrecord I'm attatching you can see a bit of the jank after I open the app fresh. I made each thumb 8px/8px because it's my personal pictures library, but you get the picture. It obviously has worse jank with their actual decoded size (which should be device width / spancount) (5 in this case). The jank is halved if I decrease the span count to 3 or 4. Here's the very simple code I'm using:

    LoadRequest request = LoadRequest.builder(((ViewHolder) holder).b.picture.getContext())
                        .key(item.getUri().toString())
                        .data(item.getUri())
                        .crossfade(false)
                        .target(((ViewHolder) holder).b.picture)
                        .build();
                Coil.execute(request);
    

    Logcat is filled with these GC related operations when doing the scrolling:

    2020-05-19 20:36:44.160 12402-12415/com.franco.graphice I/franco.graphic: Background young concurrent copying GC freed 11330(820KB) AllocSpace objects, 48(1172KB) LOS objects, 0% free, 8438KB/8438KB, paused 124us total 157.193ms
    2020-05-19 20:36:44.455 12402-12415/com.franco.graphice I/franco.graphic: Background concurrent copying GC freed 22434(2113KB) AllocSpace objects, 127(3216KB) LOS objects, 49% free, 7161KB/13MB, paused 438us total 288.432ms
    2020-05-19 20:36:45.609 12402-12415/com.franco.graphice I/franco.graphic: Background young concurrent copying GC freed 28249(2948KB) AllocSpace objects, 190(4884KB) LOS objects, 0% free, 13MB/13MB, paused 590us total 693.969ms
    2020-05-19 20:36:45.772 12402-12437/com.franco.graphice I/franco.graphic: Waiting for a blocking GC ProfileSaver
    2020-05-19 20:36:46.126 12402-12415/com.franco.graphice I/franco.graphic: Background concurrent copying GC freed 46990(4091KB) AllocSpace objects, 222(5452KB) LOS objects, 49% free, 10MB/20MB, paused 1.728ms total 515.818ms
    2020-05-19 20:36:46.126 12402-12437/com.franco.graphice I/franco.graphic: WaitForGcToComplete blocked ProfileSaver on ClassLinker for 354.762ms
    2020-05-19 20:36:48.146 12402-12415/com.franco.graphice I/franco.graphic: Background young concurrent copying GC freed 111714(5587KB) AllocSpace objects, 253(6552KB) LOS objects, 0% free, 22MB/22MB, paused 300us total 851.007ms
    2020-05-19 20:36:48.421 12402-12415/com.franco.graphice I/franco.graphic: Background concurrent copying GC freed 125680(7618KB) AllocSpace objects, 372(9332KB) LOS objects, 49% free, 8377KB/16MB, paused 654us total 258.322ms
    2020-05-19 20:36:50.169 12402-12415/com.franco.graphice I/franco.graphic: Background concurrent copying GC freed 122438(7099KB) AllocSpace objects, 230(5824KB) LOS objects, 49% free, 5686KB/11MB, paused 48us total 438.112ms
    

    Also it's a bit better when using BitmapConfig RGB_565, but just a tiny bit. With the default BitmapConfig I see tons of these logcat messages:

    2020-05-19 20:38:15.978 12923-12923/com.franco.graphice I/Choreographer: Skipped 40 frames!  The application may be doing too much work on its main thread.
    2020-05-19 20:38:16.211 12923-12965/com.franco.graphice I/OpenGLRenderer: Davey! duration=914ms; Flags=0, IntendedVsync=5662959106048, Vsync=5663625772688, OldestInputEvent=9223372036854775807, NewestInputEvent=0, HandleInputStart=5663641456128, AnimationStart=5663641473576, PerformTraversalsStart=5663642302847, DrawStart=5663719940563, SyncQueued=5663865801775, SyncStart=5663866294692, IssueDrawCommandsStart=5663867129952, SwapBuffers=5663869075161, FrameCompleted=5663874209172, DequeueBufferDuration=187000, QueueBufferDuration=1022000, 
    2020-05-19 20:38:16.321 12923-12936/com.franco.graphice I/franco.graphic: Background concurrent copying GC freed 108152(11MB) AllocSpace objects, 478(11MB) LOS objects, 50% free, 17MB/34MB, paused 201us total 1.090s
    

    Any clues or question that I can answer to help you narrow it down somehow?

    Thanks I hope this was clear enough.

    bug 
    opened by franciscofranco 42
  • A gif is playing very fast

    A gif is playing very fast

    tumblr_ku2pvuJkJG1qz9qooo1_r1_400

    Plays really fast than how it is shown in Android Gallery and Chrome. Issue occurs while using ImageDecoderDecoder. If only GifDecoder is used, gif doesn't play at all.

    How do I load this gif? Checkout #539

    This is how it looks when I load it:

    record.mp4.zip

    bug help wanted 
    opened by rupinderjeet 21
  • How to debug cancellation of load requests

    How to debug cancellation of load requests

    I am migrating from Picasso to Coil. It went quite easy as the APIs are very similar.

    I have a custom Fetcher for loading internal schemes.

    I load a list of items in a recycler view, each having a logo loaded with Coil by the custom fetcher.

    When I scroll up and down the recycler view list, I see that sometimes a wrong logo is displayed on some of the items. It seems as if the load request, which wasn't done, jumped to one of the new items coming into view. I have to scroll up and down the list a few times to trigger it.

    My guess it that the inflight request connected to the image view isn't cancelled or maybe a bitmap is reused?

    I am pretty sure it isn't a problem with the recycler view recycling of views as Picasso handled it just fine. Also the test on the items is correct. Only the logo is wrong.

    Can you guide me on how to debug this?

    question 
    opened by clhols 20
  • [coil-video] Fails to load preview for video

    [coil-video] Fails to load preview for video

    Describe the bug When I'm trying to load preview for video that I picked from my device I'm getting an exception:

    2020-05-22 23:40:14.907 27387-27387/com.example.android I/System.out: load uri: content://com.android.providers.media.documents/document/video%3A158545
    2020-05-22 23:40:14.956 27387-27462/com.example.android D/skia: --- Failed to create image decoder with message 'unimplemented'
    2020-05-22 23:40:14.956 27387-27462/com.example.android D/skia: --- Failed to create image decoder with message 'unimplemented'
    2020-05-22 23:40:14.965 27387-27387/com.example.android I/RealImageLoader: 🚨 Failed - content://com.android.providers.media.documents/document/video%3A158545 - java.lang.IllegalStateException: BitmapFactory returned a null Bitmap. Often this means BitmapFactory could not decode the image data read from the input source (e.g. network or disk) as it's not encoded as a valid image format.
    2020-05-22 23:40:14.967 27387-27387/com.example.android E/RealImageLoader: java.lang.IllegalStateException: BitmapFactory returned a null Bitmap. Often this means BitmapFactory could not decode the image data read from the input source (e.g. network or disk) as it's not encoded as a valid image format.
            at coil.decode.BitmapFactoryDecoder.decode(BitmapFactoryDecoder.kt:177)
            at coil.RealImageLoader$loadData$2.invokeSuspend(RealImageLoader.kt:349)
            at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
            at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:56)
            at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:571)
            at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.executeTask(CoroutineScheduler.kt:738)
            at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.runWorker(CoroutineScheduler.kt:678)
            at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:665)
    2020-05-22 23:40:17.922 27387-27523/com.example.android V/FA: Inactivity, disconnecting from the service
    

    Expected behavior Would like to see thumbnail

    To Reproduce The code is pretty standard

    
    val imageLoader = ImageLoader.Builder(requireContext())
                .componentRegistry {
                    add(VideoFrameFileFetcher(requireContext()))
                    add(VideoFrameUriFetcher(requireContext()))
                }
                .build()
    
    val request = LoadRequestBuilder(requireContext())
                    .data(uri)
                    .videoFrameMillis(2000)
                    .target(myImageView)
                    .build()
                imageLoader.execute(request)
    

    Version coil-version 0.11.0 Android 9 coil-video is added

    bug 
    opened by gabin8 19
  • Software rendering doesn't support hardware bitmaps

    Software rendering doesn't support hardware bitmaps

    java.lang.IllegalArgumentException: Software rendering doesn't support hardware bitmaps at android.graphics.BaseCanvas.onHwBitmapInSwMode(BaseCanvas.java:550) at android.graphics.BaseCanvas.throwIfHwBitmapInSwMode(BaseCanvas.java:557) at android.graphics.BaseCanvas.throwIfCannotDraw(BaseCanvas.java:69) at android.graphics.BaseCanvas.drawBitmap(BaseCanvas.java:127) at android.graphics.Canvas.drawBitmap(Canvas.java:1516) at android.graphics.drawable.BitmapDrawable.draw(BitmapDrawable.java:545) at android.widget.ImageView.onDraw(ImageView.java:1360) at android.view.View.draw(View.java:20332) at android.view.View.draw(View.java:20194) at android.view.ViewGroup.drawChild(ViewGroup.java:4395) at android.view.ViewGroup.dispatchDraw(ViewGroup.java:4174) at androidx.constraintlayout.widget.ConstraintLayout.dispatchDraw(ConstraintLayout.java:1767) at android.view.View.draw(View.java:20340) at android.view.View.draw(View.java:20194) at android.view.ViewGroup.drawChild(ViewGroup.java:4395) at androidx.recyclerview.widget.RecyclerView.drawChild(RecyclerView.java:5030) at android.view.ViewGroup.dispatchDraw(ViewGroup.java:4174) at android.view.View.draw(View.java:20340) at androidx.recyclerview.widget.RecyclerView.draw(RecyclerView.java:4429) at android.view.View.draw(View.java:20194) at android.view.ViewGroup.drawChild(ViewGroup.java:4395) at android.view.ViewGroup.dispatchDraw(ViewGroup.java:4174) at androidx.constraintlayout.widget.ConstraintLayout.dispatchDraw(ConstraintLayout.java:1767) at android.view.View.draw(View.java:20340) at android.view.View.draw(View.java:20194) at android.view.ViewGroup.drawChild(ViewGroup.java:4395) at android.view.ViewGroup.dispatchDraw(ViewGroup.java:4174) at android.view.View.draw(View.java:20192) at android.view.ViewGroup.drawChild(ViewGroup.java:4395) at android.view.ViewGroup.dispatchDraw(ViewGroup.java:4174) at androidx.constraintlayout.widget.ConstraintLayout.dispatchDraw(ConstraintLayout.java:1767) at android.view.View.draw(View.java:20340) at android.view.View.draw(View.java:20194) at android.view.ViewGroup.drawChild(ViewGroup.java:4395) at android.view.ViewGroup.dispatchDraw(ViewGroup.java:4174) at android.view.View.draw(View.java:20192) at android.view.ViewGroup.drawChild(ViewGroup.java:4395) at android.view.ViewGroup.dispatchDraw(ViewGroup.java:4174) at android.view.View.draw(View.java:20192) at android.view.ViewGroup.drawChild(ViewGroup.java:4395) at android.view.ViewGroup.dispatchDraw(ViewGroup.java:4174) at android.view.View.draw(View.java:20192) at android.view.ViewGroup.drawChild(ViewGroup.java:4395) at android.view.ViewGroup.dispatchDraw(ViewGroup.java:4174) at android.view.View.draw(View.java:20192) at android.view.ViewGroup.drawChild(ViewGroup.java:4395) at android.view.ViewGroup.dispatchDraw(ViewGroup.java:4174) at android.view.View.draw(View.java:20340) at com.android.internal.policy.DecorView.draw(DecorView.java:781) at android.view.ViewRootImpl.drawSoftware(ViewRootImpl.java:3582) at android.view.ViewRootImpl.draw(ViewRootImpl.java:3472) at android.view.ViewRootImpl.performDraw(ViewRootImpl.java:3244) at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:2598) at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1521) at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:7437) at android.view.Choreographer$CallbackRecord.run(Choreographer.java:965) at android.view.Choreographer.doCallbacks(Choreographer.java:777) at android.view.Choreographer.doFrame(Choreographer.java:709) at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:951) at android.os.Handler.handleCallback(Handler.java:873) at android.os.Handler.dispatchMessage(Handler.java:99) at android.os.Looper.loop(Looper.java:193)

    bug 
    opened by mt131 19
  • Enable native support for SVG format without boilerplate

    Enable native support for SVG format without boilerplate

    Currently using Glide to load SVG images and the implementation is quite clunky in order to do so. See: https://stackoverflow.com/questions/35507893/does-glide-have-a-method-for-loading-both-png-and-svg

    As a fresh new library hot off the presses, I'd like to see Coil gracefully (and optimally) handle these file formats without a ton of boilerplate.

    EDIT: WebP is already supported, so this enhancement request is more about formats that require an external library for decoding (and a Decoder).

    Thanks!

    enhancement 
    opened by 0xMatthewGroves 19
  • Priority handling for identical data request

    Priority handling for identical data request

    Is your feature request related to a problem? Please describe. At some point in my application an image can be loaded multiple times at different size, but I have no control over the order of the requests. Since I'm allowing inexact size it would be nice if there could be some way to optimize the request for the same data to be better ordered so that cache works better.

    I'm often ending up with all request running more or less simultaneously or in smaller to higher order leading to no usage of the memory cache as each request are larger than the previous one.

    Since I don't know in advance if the images will be displayed multiple times I don't want to use a tons of memory and always use Size(Original).

    I've not found a way to do anything with interceptors or the current pipeline but I maybe missed something.

    enhancement 
    opened by Tolriq 18
  • Check if view is attached to window before checking hwAcceleration

    Check if view is attached to window before checking hwAcceleration

    I've been able to reproduce the issue sometimes which led me to believe this is some kind of a race condition in checking the hw acceleration capabilities for which we need the View to be attached to the window. To be safe, I now check if we're attached to window before checking for the HW acceleration.

    Please test and let me know if this works for you.

    Signed-off-by: Mario Danic [email protected]

    opened by mario 16
  • Image flickers when url changes for rememberImagePainter

    Image flickers when url changes for rememberImagePainter

    Currently I'm using a library to reorder items in a LazyColumn. The library works and functions as expected. The issue I'm running into is that when an item is reordered in the list, it causes a recomposition because my state has changed since the position of the item has changed. This is fine, but when items in my list recompose, they might have different urls so it tries to load the new image for both items that had their positions change. This causes a flicker as it tries to load new images. I've tried to use caching to prevent rememberImagePainter from having to go fetch the image again but I don't think that's how that works. I've tried to prevent the request from going through by providing an ExecuteCallback that returned false if the state wasn't empty and that didn't work either.

    I would expect to be able to configure coil to not re-load an image when a url changes but instead use a cached version if it exists.

    I'm using version 1.3.2 and it's not device specific.

    opened by cj1098 15
  • Images cropped while load for the first time in recycler view if I kept scrolling

    Images cropped while load for the first time in recycler view if I kept scrolling

    Describe the bug I have some images cropped when loading them for the first time and kept scrolling while loading

    Expected behavior All Images should be fully loaded

    To Reproduce Load about 10 images in recycler view and start scrolling

    Logs/Screenshots Screen record: https://drive.google.com/file/d/1zBgkdsWDcEoFWy8FU66Uud0VTgF9j_pJ/view?usp=sharing

    Version I am on version 1.1.1 , It was tested on android 10

    bug needs info 
    opened by Omar-Alnajjar 15
  • Get the image file from a preloaded image

    Get the image file from a preloaded image

    Is your feature request related to a problem? Please describe. I'm looking for a way to get the image file from a preloaded image, but seems Coil lacks this feature at the moment.

    Describe the solution you'd like On Glide I do:

    val preloadedImageFile = Glide
        .with(context)
        .downloadOnly()
        .load(imageUrl)
        .submit()
        .get()
    

    Would be nice if we have at least one of these options in Coil:

    Coil.getFile(imageUrl)
    
    Coil.load(context, imageUrl) {
        target(object : FileTarget {
            override fun onSuccess(result: File) {
                
            }
        })
    }
    
    enhancement 
    opened by adrielcafe 15
  • Update dependency androidx.test:runner to v1.5.2

    Update dependency androidx.test:runner to v1.5.2

    Mend Renovate

    This PR contains the following updates:

    | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | androidx.test:runner | 1.5.0 -> 1.5.2 | age | adoption | passing | confidence |


    Configuration

    📅 Schedule: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined).

    🚦 Automerge: Disabled by config. Please merge this manually once you are satisfied.

    Rebasing: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.

    🔕 Ignore: Close this PR and you won't be reminded about this update again.


    • [ ] If you want to rebase/retry this PR, check this box

    This PR has been generated by Mend Renovate. View repository job log here.

    opened by renovate[bot] 0
  • Update dependency androidx.test.ext:junit-ktx to v1.1.5

    Update dependency androidx.test.ext:junit-ktx to v1.1.5

    Mend Renovate

    This PR contains the following updates:

    | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | androidx.test.ext:junit-ktx | 1.1.4 -> 1.1.5 | age | adoption | passing | confidence |


    Configuration

    📅 Schedule: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined).

    🚦 Automerge: Disabled by config. Please merge this manually once you are satisfied.

    Rebasing: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.

    🔕 Ignore: Close this PR and you won't be reminded about this update again.


    • [ ] If you want to rebase/retry this PR, check this box

    This PR has been generated by Mend Renovate. View repository job log here.

    opened by renovate[bot] 0
  • Update dependency androidx.test.espresso:espresso-core to v3.5.1

    Update dependency androidx.test.espresso:espresso-core to v3.5.1

    Mend Renovate

    This PR contains the following updates:

    | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | androidx.test.espresso:espresso-core | 3.5.0 -> 3.5.1 | age | adoption | passing | confidence |


    Configuration

    📅 Schedule: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined).

    🚦 Automerge: Disabled by config. Please merge this manually once you are satisfied.

    Rebasing: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.

    🔕 Ignore: Close this PR and you won't be reminded about this update again.


    • [ ] If you want to rebase/retry this PR, check this box

    This PR has been generated by Mend Renovate. View repository job log here.

    opened by renovate[bot] 0
  • Update dependency com.pinterest.ktlint:ktlint-core to v0.48.1

    Update dependency com.pinterest.ktlint:ktlint-core to v0.48.1

    Mend Renovate

    This PR contains the following updates:

    | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | com.pinterest.ktlint:ktlint-core | 0.47.1 -> 0.48.1 | age | adoption | passing | confidence |


    Release Notes

    pinterest/ktlint

    v0.48.1

    Compare Source

    Added
    Removed
    Fixed
    • An enumeration class having a primary constructor and in which the list of enum entries is followed by a semicolon then do not remove the semicolon in case it is followed by code element no-semi (#​1733)
    • Add API so that KtLint API consumer is able to process a Kotlin script snippet without having to specify a file path (#​1738)
    • Disable the standard:filename rule whenever Ktlint CLI is run with option --stdin (#​1742)
    • Fix initialization of the logger when --log-level is specified. Throw exception when an invalid value is passed. (#​1749)
    • Fix loading of custom rule set JARs.
    • Rules provided via a custom rule set JAR (Ktlint CLI) or by an API provider are enabled by default. Only rules in the experimental rule set are disabled by default. (#​1747)
    Changed
    • Update Kotlin development version to 1.8.0 and Kotlin version to 1.8.0.

    v0.48.0

    Compare Source

    Indent rule

    The indent rule has been rewritten from scratch. Solving problems in the old algorithm was very difficult. With the new algorithm this becomes a lot easier. Although the new implementation of the rule has been compared against several open source projects containing over 400,000 lines of code, it is still likely that new issues will be discovered. Please report your indentation issues so that these can be fixed as well.

    .editorconfig property to disable rules

    In the previous release (0.47.x), the .editorconfig property disabled_rules was deprecated and replaced with ktlint_disabled_rules. This latter property has now been deprecated as well in favour of a more flexible and better maintainable solution. Rule and rule sets can now be enabled/disabled with a separate property per rule (set). Please read deprecation of (ktlint_)disable_rules property for more information.

    The KtLint CLI has not been changed. Although you can still use parameter --experimental to enable KtLint's Experimental rule set, you might want to set .editorconfig property ktlint_experimental = enabled instead.

    API Changes & RuleSet providers

    If you are not an API consumer or Rule Set provider then you can skip this section.

    Class relocations

    Classes below have been relocated:

    • Class com.pinterest.ktlint.core.api.UsesEditorConfigProperties.EditorConfigProperty has been replaced with com.pinterest.ktlint.core.api.editorconfig.EditorConfigProperty.
    • Class com.pinterest.ktlint.core.KtLintParseException has been replaced with com.pinterest.ktlint.core.api.KtLintParseException.
    • Class com.pinterest.ktlint.core.RuleExecutionException has been replaced with com.pinterest.ktlint.core.api.KtLintRuleException.
    • Class com.pinterest.ktlint.reporter.format.internal.Color has been moved to com.pinterest.ktlint.reporter.format.Color.
    • Class com.pinterest.ktlint.reporter.plain.internal.Color has been moved to com.pinterest.ktlint.reporter.plain.Color.
    Invoking lint and format

    This is the last release that supports the ExperimentalParams to invoke the lint and format functions of KtLint. The ExperimentalParams contains a mix of configuration settings which are not dependent on the file/code which is to be processed. Other parameters in that class describe the code/file to be processed but can be configured inconsistently (for example a file with name "foo.kt" could be marked as a Kotlin Script file).

    The static object KtLint is deprecated and replaced by class KtLintRuleEngine which is configured with KtLintRuleEngineConfiguration. The instance of the KtLintRuleEngine is intended to be reused for scanning all files in a project and should not be recreated per file.

    Both lint and format are simplified and can now be called for a code block or for an entire file.

    import java.io.File
    
    // Define a reusable instance of the KtLint Rule Engine
    val ktLintRuleEngine = KtLintRuleEngine(
      // Define configuration
    )
    
    // Process a collection of files
    val files: Set<File> // Collect files in a convenient way
    files.forEach(file in files) {
        ktLintRuleEngine.lint(file) {
            // Handle lint violations
        }
    }
    
    // or process a code sample for a given filepath
    ktLintRuleEngine.lint(
      code = "code to be linted",
      filePath = Path("/path/to/source/file")
    ) {
      // Handle lint violations
    }
    
    Retrieve .editorconfigs

    The list of .editorconfig files which will be accessed by KtLint when linting or formatting a given path can now be retrieved with the new API KtLint.editorConfigFilePaths(path: Path): List<Path>.

    This API can be called with either a file or a directory. It's intended usage is that it is called once with the root directory of a project before actually linting or formatting files of that project. When called with a directory path, all .editorconfig files in the directory or any of its subdirectories (except hidden directories) are returned. In case the given directory does not contain an .editorconfig file or if it does not contain the root=true setting, the parent directories are scanned as well until a root .editorconfig file is found.

    Calling this API with a file path results in the .editorconfig files that will be accessed when processing that specific file. In case the directory in which the file resides does not contain an .editorconfig file or if it does not contain the root=true setting, the parent directories are scanned until a root .editorconfig file is found.

    Psi filename replaces FILE_PATH_USER_DATA_KEY

    Constant KtLint.FILE_PATH_USER_DATA_KEY is deprecated and will be removed in KtLint version 0.49.0. The file name will be passed correctly to the node with element type FILE and can be retrieved as follows:

    if (node.isRoot()) {
        val fileName = (node.psi as? KtFile)?.name
        ...
    }
    
    Added
    • Wrap blocks in case the max line length is exceeded or in case the block contains a new line wrapping (#​1643)
    • patterns can be read in from stdin with the --patterns-from-stdin command line options/flags (#​1606)
    • Add basic formatting for context receiver in indent rule and new experimental rule context-receiver-wrapping (#​1672)
    • Add naming rules for classes and objects (class-naming), functions (function-naming) and properties (property-naming) (#​44)
    • Add new built-in reporter plain-summary which prints a summary the number of violation which have been autocorrected or could not be autocorrected, both split by rule.
    Fixed
    • Let a rule process all nodes even in case the rule is suppressed for a node so that the rule can update the internal state (#​1644)
    • Read .editorconfig when running CLI with options --stdin and --editorconfig (#​1651)
    • Do not add a trailing comma in case a multiline function call argument is found but no newline between the arguments trailing-comma-on-call-site (#​1642)
    • Add missing ktlint_disabled_rules to exposed editorConfigProperties (#​1671)
    • Do not add a second trailing comma, if the original trailing comma is followed by a KDOC trailing-comma-on-declaration-site and trailing-comma-on-call-site (#​1676)
    • A function signature preceded by an annotation array should be handled similar as function preceded by a singular annotation function-signature (#​1690)
    • Fix offset of annotation violations
    • Fix line offset when blank line found between class and primary constructor
    • Remove needless blank line between class followed by EOL, and primary constructor
    • Fix offset of unexpected linebreak before assignment
    • Remove whitespace before redundant semicolon if the semicolon is followed by whitespace
    Changed
    • Update Kotlin development version to 1.8.0-RC and Kotlin version to 1.7.21.
    • The default value for trailing comma's on call site is changed to true unless the android codestyle is enabled. Note that KtLint from a consistency viewpoint enforces the trailing comma on call site while default IntelliJ IDEA formatting only allows the trailing comma but leaves it up to the developer's discretion. (#​1670)
    • The default value for trailing comma's on declaration site is changed to true unless the android codestyle is enabled. Note that KtLint from a consistency viewpoint enforces the trailing comma on declaration site while default IntelliJ IDEA formatting only allows the trailing comma but leaves it up to the developer's discretion. (#​1669)
    • CLI options --debug, --trace, --verbose and -v are replaced with --log-level=<level> or the short version `-l=, see CLI log-level. (#​1632)
    • In CLI, disable logging entirely by setting --log-level=none or -l=none (#​1652)
    • Rewrite indent rule. Solving problems in the old algorithm was very difficult. With the new algorithm this becomes a lot easier. Although the new implementation of the rule has been compared against several open source projects containing over 400,000 lines of code, it is still likely that new issues will be discovered. Please report your indentation issues so that these can be fixed as well. (#​1682, #​1321, #​1200, #​1562, #​1563, #​1639)
    • Add methods "ASTNode.upsertWhitespaceBeforeMe" and "ASTNode.upsertWhitespaceAfterMe" as replacements for "LeafElement.upsertWhitespaceBeforeMe" and "LeafElement.upsertWhitespaceAfterMe". The new methods are more versatile and allow code to be written more readable in most places. (#​1687)
    • Rewrite indent rule. Solving problems in the old algorithm was very difficult. With the new algorithm this becomes a lot easier. Although the new implementation of the rule has been compared against several open source projects containing over 400,000 lines of code, it is still likely that new issues will be discovered. Please report your indentation issues so that these can be fixed as well. (#​1682, #​1321, #​1200, #​1562, #​1563, #​1639, #​1688)
    • Add support for running tests on java 19, remove support for running tests on java 18.
    • Update io.github.detekt.sarif4k:sarif4k version to 0.2.0 (#​1701).

    Configuration

    📅 Schedule: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined).

    🚦 Automerge: Disabled by config. Please merge this manually once you are satisfied.

    Rebasing: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.

    🔕 Ignore: Close this PR and you won't be reminded about this update again.


    • [ ] If you want to rebase/retry this PR, check this box

    This PR has been generated by Mend Renovate. View repository job log here.

    opened by renovate[bot] 0
  • Apply content scaling to placeholder/error Painter as well

    Apply content scaling to placeholder/error Painter as well

    Is your feature request related to a problem? Please describe.

    I load an image. I know the dimensions beforehand, so I can reserve the space with a simple Painter which paints a solid color so that the layout will not jump. The painter has an intrinsic size equal to the image.

        AsyncImage(
            model = ImageRequest.Builder(context).data("https://raw.githubusercontent.com/coil-kt/coil/main/logo.svg").crossfade(true).build(),
            placeholder = PlaceholderPainter(
                MaterialTheme.colorScheme.surfaceVariant,
                width = 403, height = 202,
            ),
            contentDescription = contentDescription,
            contentScale = ContentScale.FillWidth
            modifier = modifier,
            alignment = Alignment.Center, 
        )
    

    However, Coil draws the placeholder exactly at the intrinsic size, and does not scale it according to the parameter. The layout still jumps.

    Describe the solution you'd like

    I would like Coil to respect the contentScale setting for the passed placeholder, so that it takes the exact same size as the loaded image.

    I know I can scale the intrinsic size of the Painter according to the container dimensions, but I think it would be nice if Coil resized it automatically.

    Coil version 2.2.2

    enhancement 
    opened by digitalheir 0
  • Didn't load image from disk cache if it loaded with empty string header

    Didn't load image from disk cache if it loaded with empty string header

    Describe the bug If server returns image with empty string in header, then image can't load from disc next session

    To Reproduce If server returns image with empty string in header, then image can't load from disc next session.

    Logs/Screenshots java.lang.IllegalArgumentException: name is empty at okhttp3.Headers$Companion.checkName(Headers.kt:438) at okhttp3.Headers$Companion.access$checkName(Headers.kt:362) at okhttp3.Headers$Builder.addUnsafeNonAscii(Headers.kt:270) at coil.util.-Utils.addUnsafeNonAscii(Utils.kt:239) at coil.network.CacheResponse.(CacheResponse.kt:29) at coil.fetch.HttpUriFetcher.toCacheResponse(HttpUriFetcher.kt:255)

    Version Coil 2.2.2

    To Fix if coil.util.Utils rewrite

    internal fun Headers.Builder.addUnsafeNonAscii(line: String) = apply { val index = line.indexOf(':') require(index != -1) { "Unexpected header: $line" } val name = line.substring(0, index).trim() val content = line.substring(index + 1) require(name.isNotEmpty()) { "Header name can't be empty" } addUnsafeNonAscii(name, content) }

    opened by mmarashan 0
Releases(2.2.2)
Owner
Coil
Image loading for Android backed by Kotlin Coroutines.
Coil
Android Asynchronous Networking and Image Loading

Android Asynchronous Networking and Image Loading Download Maven Git Features Kotlin coroutine/suspend support Asynchronously download: Images into Im

Koushik Dutta 6.3k Dec 27, 2022
Library to handle asynchronous image loading on Android.

WebImageLoader WebImageLoader is a library designed to take to hassle out of handling images on the web. It has the following features: Images are dow

Alexander Blom 102 Dec 22, 2022
🍂 Jetpack Compose image loading library which can fetch and display network images using Glide, Coil, and Fresco.

?? Jetpack Compose image loading library which can fetch and display network images using Glide, Coil, and Fresco.

Jaewoong Eum 1.4k Jan 2, 2023
Powerful and flexible library for loading, caching and displaying images on Android.

Universal Image Loader The great ancestor of modern image-loading libraries :) UIL aims to provide a powerful, flexible and highly customizable instru

Sergey Tarasevich 16.8k Jan 8, 2023
Compose Image library for Kotlin Multiplatform.

Compose ImageLoader Compose Image library for Kotlin Multiplatform. Setup Add the dependency in your common module's commonMain sourceSet kotlin {

Seiko 45 Dec 29, 2022
🦄 Android Pokedex-AR using ARCore, Sceneform, Hilt, Coroutines, Flow, Jetpack based on MVVM architecture.

Pokedex-AR Pokedex-AR is a small demo application based on AR, modern Android application tech-stacks, and MVVM architecture. This project focuses on

Jaewoong Eum 535 Dec 9, 2022
A powerful image downloading and caching library for Android

Picasso A powerful image downloading and caching library for Android For more information please see the website Download Download the latest AAR from

Square 18.4k Jan 6, 2023
An Android transformation library providing a variety of image transformations for Glide.

Glide Transformations An Android transformation library providing a variety of image transformations for Glide. Please feel free to use this. Are you

Daichi Furiya 9.7k Dec 30, 2022
An android image compression library.

Compressor Compressor is a lightweight and powerful android image compression library. Compressor will allow you to compress large photos into smaller

Zetra 6.7k Jan 9, 2023
An Android transformation library providing a variety of image transformations for Picasso

Picasso Transformations An Android transformation library providing a variety of image transformations for Picasso. Please feel free to use this. Are

Daichi Furiya 1.7k Jan 5, 2023
Image Picker for Android 🤖

Image Picker for Android ??

Esa Firman 1k Dec 31, 2022
Luban(鲁班)—Image compression with efficiency very close to WeChat Moments/可能是最接近微信朋友圈的图片压缩算法

Luban ?? English Documentation Luban(鲁班) —— Android图片压缩工具,仿微信朋友圈压缩策略。 Luban-turbo —— 鲁班项目的turbo版本,查看trubo分支。 写在前面 家境贫寒,工作繁忙。只能不定期更新,还望网友们见谅! 项目描述 目前做A

郑梓斌 13.1k Jan 7, 2023
ZoomableComposeImage - A zoomable image for jetpack compose

ZoomableComposeImage - A zoomable image for jetpack compose

RERERE 10 Dec 11, 2022
ComposeImageBlurhash is a Jetpack Compose component with the necessary implementation to display a blurred image

compose-image-blurhash ComposeImageBlurhash is a Jetpack Compose component with the necessary implementation to display a blurred image while the real

Orlando Novas Rodriguez 24 Nov 18, 2022
Easy to use, lightweight custom image view with rounded corners.

RoundedImageView Easy to use, lightweight custom image view with rounded corners. Explore the docs » View Demo · Report Bug · Request Feature About Th

Melik Mehmet Özyildirim 6 Dec 23, 2021
load-the-image Apply to compose-jb(desktop), Used to load network and local pictures.

load-the-image load-the-image Apply to compose-jb(desktop), Used to load network and local pictures. ?? Under construction It may change incompatibly

lt_taozi 13 Dec 29, 2022
A simple & efficient anti-afk plugin written in kotlin

Chat Box A simple & efficient anti-afk plugin written in kotlin. Features Permission based afk bypasses Configurable settings Dependencies helper Comp

GrowlyX 5 Mar 5, 2022
An Android library for managing images and the memory they use.

Fresco Fresco is a powerful system for displaying images in Android applications. Fresco takes care of image loading and display, so you don't have to

Facebook 16.9k Jan 8, 2023
Adds touch functionality to Android ImageView.

TouchImageView for Android Capabilities TouchImageView extends ImageView and supports all of ImageView’s functionality. In addition, TouchImageView ad

Michael Ortiz 2.6k Jan 1, 2023