一个旧项目需要添加仅wifi下加载图片的配置功能,因为该项目并没有封装图片加载,只是直接使用了glide加载图片,常规改造方法工作量巨大,于是有了这篇。
实现思路是通过自定义的Loader,实现wifi下正常逻辑,非wifi下跳过下载流程。
官方文档,https://muyangmin.github.io/glide-docs-cn/tut/custom-modelloader.html
自定义Fetcher
这个类是图片下载的核心逻辑。
class NewsFetcher(private val client: Call.Factory, private val url: GlideUrl) :
DataFetcher<InputStream>, okhttp3.Callback {
private val TAG = NewsFetcher::class.java.name
@Volatile
private var call: Call? = null
private var callback: DataFetcher.DataCallback<in InputStream>? = null
private var stream: InputStream? = null
private var responseBody: ResponseBody? = null
override fun loadData(priority: Priority, callback: DataFetcher.DataCallback<in InputStream>) {
if (不满足下载图片的情况) {
return
}
//使用okhttp 请求图片
val requestBuilder = Request.Builder().url(url.toStringUrl())
for ((key, value) in url.headers) {
requestBuilder.addHeader(key, value)
}
val request = requestBuilder.build()
this.callback = callback
call = client.newCall(request)
call?.enqueue(this)
}
override fun cleanup() {
try {
stream?.close()
} catch (e: IOException) {
// Ignored
}
responseBody?.close()
callback = null
}
override fun cancel() {
val local = call
local?.cancel()
}
override fun getDataClass(): Class<InputStream> = InputStream::class.java
override fun getDataSource(): DataSource = DataSource.REMOTE
override fun onFailure(call: Call, e: IOException) {
if (Log.isLoggable(TAG, Log.DEBUG)) {
Log.d(TAG, "OkHttp failed to obtain result", e)
}
callback?.onLoadFailed(e)
}
override fun onResponse(call: Call, response: Response) {
responseBody = response.body()
if (response.isSuccessful) {
val contentLength =
Preconditions.checkNotNull(responseBody).contentLength()
stream = ContentLengthInputStream.obtain(responseBody!!.byteStream(), contentLength)
callback?.onDataReady(stream)
} else {
callback?.onLoadFailed(HttpException(response.message(), response.code()))
}
}
}
ModelLoader
- 定义一个okhttp单例
object NewsInternalClient {
val internalClient: Call.Factory = OkHttpClient()
}
- modelLoader
class NewsModelLoader(private val client: Call.Factory) : ModelLoader<GlideUrl, InputStream> {
override fun handles(url: GlideUrl): Boolean {
return true
}
override fun buildLoadData(
model: GlideUrl,
width: Int,
height: Int,
options: Options
): ModelLoader.LoadData<InputStream>? {
return ModelLoader.LoadData(model,
NewsFetcher(client, model)
)
}
class Factory : ModelLoaderFactory<GlideUrl, InputStream> {
override fun build(multiFactory: MultiModelLoaderFactory): ModelLoader<GlideUrl, InputStream> {
return NewsModelLoader(NewsInternalClient.internalClient)
}
override fun teardown() {
// Do nothing, this instance doesn't own the client.
}
}
}
LibraryGlideModule
因为我的逻辑是在module中,所以使用LibraryGlideModule,如果你的实在app module则使用AppGlideModule。
@GlideModule
class NewsGlideModel : LibraryGlideModule() {
override fun registerComponents(context: Context, glide: Glide, registry: Registry) {
registry.replace(
GlideUrl::class.java, InputStream::class.java,
NewsModelLoader.Factory()
)
}
}
最后
到这里你的配置还不会生效,需要在app module中编写一个空的AppGlideModule
@GlideModule
public class MyAppGlideModel extends AppGlideModule {
}
在使用到glide注解的模块添加处理器
kapt 'com.github.bumptech.glide:compiler:4.11.0'
大功告成,正常使用glide即可。
网友评论