fixup! Implement image request merging in standalone Interceptor
This commit is contained in:
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)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in new issue
Block a user