fixup! Implement image request merging in standalone Interceptor

This commit is contained in:
FooIbar authored and tarsin committed 2023-02-27 02:32:33 +08:00
1 parent 90b6106fb4
commit 2fea94ce9b
3 files changed
+25 -15

No files matched your search

@@ -27,6 +27,7 @@ import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.ProcessLifecycleOwner import androidx.lifecycle.ProcessLifecycleOwner
import coil.ImageLoader import coil.ImageLoader
import coil.ImageLoaderFactory import coil.ImageLoaderFactory
import coil.util.DebugLogger
import com.hippo.Native import com.hippo.Native
import com.hippo.ehviewer.client.EhCookieStore import com.hippo.ehviewer.client.EhCookieStore
import com.hippo.ehviewer.client.EhDns import com.hippo.ehviewer.client.EhDns
@@ -186,6 +187,7 @@ class EhApplication : Application(), DefaultLifecycleObserver, ImageLoaderFactor
okHttpClient(okHttpClient) okHttpClient(okHttpClient)
components { add(MergeInterceptor) } components { add(MergeInterceptor) }
crossfade(300) crossfade(300)
if (BuildConfig.DEBUG) logger(DebugLogger())
}.build() }.build()
} }
@@ -15,7 +15,8 @@ import kotlin.coroutines.Continuation
import kotlin.coroutines.resume import kotlin.coroutines.resume
object MergeInterceptor : Interceptor { object MergeInterceptor : Interceptor {
private val pendingContinuationMap: HashMap<String, MutableList<Continuation<Unit>>> = hashMapOf() private val pendingContinuationMap: HashMap<String, MutableList<Continuation<Unit>>> =
hashMapOf()
private val pendingContinuationMapLock = Mutex() private val pendingContinuationMapLock = Mutex()
private val notifyScope = CoroutineScope(Dispatchers.IO + SupervisorJob()) private val notifyScope = CoroutineScope(Dispatchers.IO + SupervisorJob())
override suspend fun intercept(chain: Interceptor.Chain): ImageResult { override suspend fun intercept(chain: Interceptor.Chain): ImageResult {
@@ -23,18 +24,8 @@ object MergeInterceptor : Interceptor {
val originListener = originRequest.listener val originListener = originRequest.listener
val key = originRequest.data as String val key = originRequest.data as String
val newRequest = ImageRequest.Builder(originRequest).listener( val newRequest = ImageRequest.Builder(originRequest).listener(
{ originListener?.onStart(it) }, {},
{ {}, // Only original request's onStart and onCancel will get called
originListener?.onCancel(it)
notifyScope.launch {
pendingContinuationMapLock.withLock {
// Wake up a pending continuation to continue executing task
val successor = pendingContinuationMap[key]?.removeFirstOrNull()?.apply { resume(Unit) }
// If no successor, delete this entry from hashmap
successor ?: pendingContinuationMap.remove(key)
}
}
},
{ request, result -> { request, result ->
originListener?.onError(request, result) originListener?.onError(request, result)
// Wake all pending continuations since this request is to be failed // Wake all pending continuations since this request is to be failed
@@ -72,4 +63,16 @@ object MergeInterceptor : Interceptor {
return withContext(originRequest.interceptorDispatcher) { chain.proceed(newRequest) } return withContext(originRequest.interceptorDispatcher) { chain.proceed(newRequest) }
} }
fun onCancel(key: String) {
notifyScope.launch {
pendingContinuationMapLock.withLock {
// Wake up a pending continuation to continue executing task
val successor =
pendingContinuationMap[key]?.removeFirstOrNull()?.apply { resume(Unit) }
// If no successor, delete this entry from hashmap
successor ?: pendingContinuationMap.remove(key)
}
}
}
} }
@@ -27,6 +27,7 @@ import coil.size.Size
import com.hippo.drawable.PreciselyClipDrawable import com.hippo.drawable.PreciselyClipDrawable
import com.hippo.ehviewer.EhApplication import com.hippo.ehviewer.EhApplication
import com.hippo.ehviewer.R import com.hippo.ehviewer.R
import com.hippo.ehviewer.coil.MergeInterceptor
private val application = EhApplication.application private val application = EhApplication.application
private val errorDrawable = AppCompatResources.getDrawable(application, R.drawable.image_failed) private val errorDrawable = AppCompatResources.getDrawable(application, R.drawable.image_failed)
@@ -84,7 +85,10 @@ open class LoadImageView @JvmOverloads constructor(
if (!crossfade) crossfade(false) if (!crossfade) crossfade(false)
listener( listener(
{ setRetry(false) }, { setRetry(false) },
{ setRetry(true) }, {
MergeInterceptor.onCancel(url)
setRetry(true)
},
{ _, _ -> { _, _ ->
super.setImageDrawable(errorDrawable) super.setImageDrawable(errorDrawable)
setRetry(true) setRetry(true)
@@ -102,7 +106,8 @@ open class LoadImageView @JvmOverloads constructor(
var newDrawable = drawable var newDrawable = drawable
if (newDrawable != null) { if (newDrawable != null) {
if (Integer.MIN_VALUE != mOffsetX) { if (Integer.MIN_VALUE != mOffsetX) {
newDrawable = PreciselyClipDrawable(newDrawable, mOffsetX, mOffsetY, mClipWidth, mClipHeight) newDrawable =
PreciselyClipDrawable(newDrawable, mOffsetX, mOffsetY, mClipWidth, mClipHeight)
} }
onPreSetImageDrawable(newDrawable, true) onPreSetImageDrawable(newDrawable, true)
} }