Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions coil-base/api/coil-base.api
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ public final class coil/ImageLoader$Builder {
public final fun memoryCache (Lcoil/memory/MemoryCache;)Lcoil/ImageLoader$Builder;
public final fun memoryCachePolicy (Lcoil/request/CachePolicy;)Lcoil/ImageLoader$Builder;
public final fun networkCachePolicy (Lcoil/request/CachePolicy;)Lcoil/ImageLoader$Builder;
public final fun networkObserverEnabled (Z)Lcoil/ImageLoader$Builder;
public final fun okHttpClient (Lkotlin/jvm/functions/Function0;)Lcoil/ImageLoader$Builder;
public final fun okHttpClient (Lokhttp3/OkHttpClient;)Lcoil/ImageLoader$Builder;
public final fun placeholder (I)Lcoil/ImageLoader$Builder;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ class SystemCallbacksTest {

@Test
fun imageLoaderIsFreedWithoutShutdown() {
val systemCallbacks = SystemCallbacks(ImageLoader(context) as RealImageLoader, context)
val systemCallbacks = SystemCallbacks(ImageLoader(context) as RealImageLoader, context, true)

val bitmaps = mutableListOf<Bitmap>()
while (systemCallbacks.imageLoader.get() != null) {
Expand Down Expand Up @@ -69,7 +69,7 @@ class SystemCallbacksTest {
options = ImageLoaderOptions(),
logger = null
)
val systemCallbacks = SystemCallbacks(imageLoader, context)
val systemCallbacks = SystemCallbacks(imageLoader, context, true)

strongMemoryCache.set(
key = MemoryCache.Key("1"),
Expand Down
14 changes: 14 additions & 0 deletions coil-base/src/main/java/coil/ImageLoader.kt
Original file line number Diff line number Diff line change
Expand Up @@ -328,6 +328,20 @@ interface ImageLoader {
this.memoryCache = null
}

/**
* Enables short circuiting network requests if the device is offline.
*
* If true, reading from the network will automatically be disabled if the device is offline.
* If a cached response is unavailable the request will fail with a '504 Unsatisfiable Request' response.
*
* If false, the image loader will attempt a network request even if the device is offline.
*
* Default: true
*/
fun networkObserverEnabled(enable: Boolean) = apply {
this.options = this.options.copy(networkObserverEnabled = enable)
}

/**
* Enables weak reference tracking of loaded images.
*
Expand Down
2 changes: 1 addition & 1 deletion coil-base/src/main/java/coil/RealImageLoader.kt
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ internal class RealImageLoader(
memoryCache.strongMemoryCache, memoryCache.weakMemoryCache)
private val requestService = RequestService(logger)
private val drawableDecoder = DrawableDecoderService(bitmapPool)
private val systemCallbacks = SystemCallbacks(this, context)
private val systemCallbacks = SystemCallbacks(this, context, options.networkObserverEnabled)
private val registry = componentRegistry.newBuilder()
// Mappers
.add(StringMapper())
Expand Down
11 changes: 10 additions & 1 deletion coil-base/src/main/java/coil/network/NetworkObserver.kt
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,16 @@ internal interface NetworkObserver {
private const val TAG = "NetworkObserver"

/** Create a new [NetworkObserver] instance. */
operator fun invoke(context: Context, listener: Listener, logger: Logger?): NetworkObserver {
operator fun invoke(
context: Context,
isEnabled: Boolean,
listener: Listener,
logger: Logger?
): NetworkObserver {
if (!isEnabled) {
return EmptyNetworkObserver
}

val connectivityManager: ConnectivityManager? = context.getSystemService()
if (connectivityManager == null || !context.isPermissionGranted(ACCESS_NETWORK_STATE)) {
logger?.log(TAG, Log.WARN) { "Unable to register network observer." }
Expand Down
3 changes: 2 additions & 1 deletion coil-base/src/main/java/coil/util/ImageLoaderOptions.kt
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,6 @@ import coil.RealImageLoader
*/
internal data class ImageLoaderOptions(
val addLastModifiedToFileCacheKey: Boolean = true,
val launchInterceptorChainOnMainThread: Boolean = true
val launchInterceptorChainOnMainThread: Boolean = true,
val networkObserverEnabled: Boolean = true
)
5 changes: 3 additions & 2 deletions coil-base/src/main/java/coil/util/SystemCallbacks.kt
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,12 @@ import java.util.concurrent.atomic.AtomicBoolean
*/
internal class SystemCallbacks(
imageLoader: RealImageLoader,
private val context: Context
private val context: Context,
isNetworkObserverEnabled: Boolean
) : ComponentCallbacks2, NetworkObserver.Listener {

@VisibleForTesting internal val imageLoader = WeakReference(imageLoader)
private val networkObserver = NetworkObserver(context, this, imageLoader.logger)
private val networkObserver = NetworkObserver(context, isNetworkObserverEnabled, this, imageLoader.logger)

@Volatile private var _isOnline = networkObserver.isOnline
private val _isShutdown = AtomicBoolean(false)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ class EngineInterceptorTest {
strongMemoryCache = strongMemoryCache,
memoryCacheService = MemoryCacheService(referenceCounter, strongMemoryCache, weakMemoryCache),
requestService = RequestService(null),
systemCallbacks = SystemCallbacks(ImageLoader(context) as RealImageLoader, context),
systemCallbacks = SystemCallbacks(ImageLoader(context) as RealImageLoader, context, true),
drawableDecoder = DrawableDecoderService(bitmapPool),
logger = null
)
Expand Down