Browse Source

glide 封装

master
suliang 2 years ago
parent
commit
b735a3ad0f

+ 20
- 0
app/src/main/java/com/xkl/cdl/module/XKLApplication.kt View File

@@ -0,0 +1,20 @@
package com.xkl.cdl.module

import android.app.Application

/**
* author suliang
* create 2022/3/14 11:27
* Describe:
*/
class XKLApplication : Application() {

override fun onCreate() {
super.onCreate()

// ImageLoader.mStrategy = GlideLoaderStrategy()


}

}

+ 8
- 3
app/src/main/java/com/xkl/cdl/module/splash/SplashActivity.kt View File

@@ -4,12 +4,12 @@ import android.annotation.SuppressLint
import android.os.Bundle
import android.os.Looper
import android.view.View
import com.bumptech.glide.load.resource.bitmap.CircleCrop
import com.suliang.common.base.activity.BaseActivity
import com.suliang.common.util.LogUtil
import com.suliang.common.util.image.ImageLoader
import com.suliang.common.util.image.ImageLoaderOption
import com.suliang.common.util.media.*
import com.suliang.common.util.media.MPManager.addPlayListener
import com.suliang.common.util.thread.AppExecutors
import com.xkl.cdl.R
import com.xkl.cdl.databinding.ActivitySplashBinding

@@ -30,7 +30,12 @@ class SplashActivity : BaseActivity<ActivitySplashBinding>() {


override fun loadData() {
ImageLoader.loadImage(R.mipmap.ic_launcher)
ImageLoader.loadImage(ImageLoaderOption().apply {
targetView = binding.img
resourceId = R.drawable.illustration_splash
centerInsideEnable = true
circleEnable = true
})
}

val util:IMP = MPManager.apply {

+ 3
- 1
build.gradle View File

@@ -35,7 +35,7 @@ ext {
appcompat_version: "1.4.1",
material_version : "1.3.0",
lifecycle_version: "2.5.0-alpha02",
glide_version : "4.1.0",
glide_version : "4.11.0",
]
//必须依赖
dependencies_required = [
@@ -72,6 +72,8 @@ ext {
//Glide 依赖和配置
Glide : "com.github.bumptech.glide:glide:${versions.glide_version}",
GlideCompiler : "com.github.bumptech.glide:compiler:${versions.glide_version}",
//Glide translation
GlideTranslation: "jp.wasabeef:glide-transformations:4.3.0"
]



+ 9
- 3
lib/common/build.gradle View File

@@ -46,11 +46,17 @@ dependencies {
rootProject.ext.dependencies_required.each{ k,v -> implementation v}
testImplementation rootProject.ext.dependencies_testImplementation.junit
rootProject.ext.dependencies_androidTestImplementation.each{ k,v -> androidTestImplementation v}

def customDependencies = rootProject.ext.dependencies_custom

//状态栏
api rootProject.ext.dependencies_custom.UltimateBarX
api customDependencies.UltimateBarX
//glide
api rootProject.ext.dependencies_custom.Glide
kapt rootProject.ext.dependencies_custom.GlideCompiler
api customDependencies.Glide
kapt customDependencies.GlideCompiler
//glide translation
api customDependencies.GlideTranslation



}

+ 9
- 1
lib/common/proguard-rules.pro View File

@@ -18,4 +18,12 @@

# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile
#-renamesourcefileattribute SourceFile


-keep public class * implements com.bumptech.glide.module.GlideModule
-keep public class * extends com.bumptech.glide.module.AppGlideModule
-keep public enum com.bumptech.glide.load.ImageHeaderParser$** {
**[] $VALUES;
public *;
}

+ 10
- 0
lib/common/src/main/AndroidManifest.xml View File

@@ -1,7 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="com.suliang.common">

<!--网络权限-->
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<!--本地外置存储权限-->
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"
tools:ignore="ScopedStorage" />


<!--networkSecurityConfig,usesCleartextTraffic 二选一都可以9.0-P以上高版本的http连接,否则连接失败
android:networkSecurityConfig="@xml/network_security_config"
android:usesCleartextTraffic="true"

+ 0
- 30
lib/common/src/main/java/com/suliang/common/util/image/GlideLoader.kt View File

@@ -1,30 +0,0 @@
package com.suliang.common.util.image

import java.lang.Exception

/**
* author suliang
* create 2022/3/11 16:14
* Describe: Glide 加载的具体实现
* https://juejin.cn/post/6844903463134953479#heading-3
*/
internal class GlideLoader: ILoaderStrategy {

override fun loadImage(option: LoaderOptions) {
when{
option.targetView == null -> throw Exception("Glide Option targetView is not empty")

}
}




override fun clearMemoryCache() {

}

override fun clearDiskCache() {

}
}

+ 182
- 0
lib/common/src/main/java/com/suliang/common/util/image/GlideLoaderStrategy.kt View File

@@ -0,0 +1,182 @@
package com.suliang.common.util.image

import android.graphics.Bitmap
import android.graphics.drawable.Drawable
import com.bumptech.glide.Glide
import com.bumptech.glide.RequestBuilder
import com.bumptech.glide.load.MultiTransformation
import com.bumptech.glide.load.Transformation
import com.bumptech.glide.load.resource.bitmap.*
import com.bumptech.glide.load.resource.gif.GifDrawable
import com.suliang.common.util.AppGlobals
import jp.wasabeef.glide.transformations.BlurTransformation
import java.io.File
import kotlin.concurrent.thread


/**
* author suliang
* create 2022/3/11 16:14
* Describe: Glide 加载的具体实现
* https://juejin.cn/post/6844903463134953479#heading-3
*/
class GlideLoaderStrategy : IBaseLoaderStrategy {

override fun clearMemoryCache() {
Glide.get(AppGlobals.application).clearMemory()
}

override fun clearDiskCache() {
thread {
Glide.get(AppGlobals.application).clearDiskCache()
}
}

override fun loadImage(option: ImageLoaderOption) {
//如果上下文和图片目标有一个不存在,则报异常
if (option.context == null && option.targetView == null) {
throw Exception("the Glide Option context or targetView is not empty")
}
if (option.context == null) {
option.context = option.targetView!!.context
}
option.context?.let {
load(option)
}
}


private fun initNormalDrawableGlideRequest(option: ImageLoaderOption): RequestBuilder<Drawable> {
return GlideApp.with(option.context!!).asDrawable().load(source(option)).placeholder(option.placeholderResId)
.error(option.errorResId).fallback(option.fallback)
}

private fun initNormalFileGlideRequest(option: ImageLoaderOption): RequestBuilder<File> {
return GlideApp.with(option.context!!).asFile().load(source(option)).placeholder(option.placeholderResId)
.error(option.errorResId).fallback(option.fallback)
}

private fun initNormalBitmapGlideRequest(option: ImageLoaderOption): RequestBuilder<Bitmap> {
return GlideApp.with(option.context!!).asBitmap().load(source(option)).placeholder(option.placeholderResId)
.error(option.errorResId).fallback(option.fallback)
}

private fun initNormalGifGlideRequest(option: ImageLoaderOption): RequestBuilder<GifDrawable> {
return GlideApp.with(option.context!!).asGif().load(source(option)).placeholder(option.placeholderResId)
.error(option.errorResId).fallback(option.fallback)
}

/** 普通加载 */
private fun load(option: ImageLoaderOption) {
when {
option.asBitmap -> {
initNormalBitmapGlideRequest(option).transform(initTranslation(option)).into(option.targetView!!)
}
option.asGif -> {
initNormalGifGlideRequest(option).transform(initTranslation(option)).into(option.targetView!!)
}
option.asFile -> {
initNormalFileGlideRequest(option).transform(initTranslation(option)).into(option.targetView!!)
}
else -> {
initNormalDrawableGlideRequest(option).transform(initTranslation(option)).into(option.targetView!!)
}
}
}


private fun initTranslation(option: ImageLoaderOption): MultiTransformation<Bitmap> {
val list: MutableList<Transformation<Bitmap>> = ArrayList()
list.add(BlurTransformation(25, 3))
//gravity 模式
if (option.centerInsideEnable) {
list.add(CenterInside())
} else if (option.fitCenterEnable) {
list.add(FitCenter())
} else {
list.add(CenterCrop())
}
//圆形
if (option.circleEnable) {
list.add(CircleCrop())
}
//圆角
if (option.rounderCorners != 0) {
list.add(RoundedCorners(option.rounderCorners))
}
//模糊
if (option.blurEanble) {
list.add(BlurTransformation(25, 3))
}
return MultiTransformation(list)
}

/** 最终加载资源*/
private fun source(option: ImageLoaderOption) =
option.bitmap ?: option.drawable ?: option.uri ?: option.url ?: option.file ?: option.byteArray
?: option.resourceId


// /** 加载圆角图片 */
// private fun loadRounderCorner(option: ImageLoaderOption) {
// when {
// option.asBitmap -> {
// initNormalBitmapGlideRequest(option).transform(RoundedCorners(option.rounderCorners))
// .into(option.targetView!!)
// }
// option.asGif -> {
// initNormalGifGlideRequest(option).transform(RoundedCorners(option.rounderCorners))
// .into(option.targetView!!)
// }
// option.asFile -> {
// initNormalFileGlideRequest(option).transform(RoundedCorners(option.rounderCorners))
// .into(option.targetView!!)
// }
// else -> {
// initNormalDrawableGlideRequest(option).transform(RoundedCorners(option.rounderCorners))
// .into(option.targetView!!)
// }
// }
//// GlideApp.with(option.context).load(source(option)).transform(RoundedCorners(option.rounderCorners))
//// .into(option.targetView!!)
// }
//
// /** 加载圆形图片 */
// private fun loadCircle(option: ImageLoaderOption) {
// when {
// option.asBitmap -> {
// initNormalBitmapGlideRequest(option).transform(CircleCrop()).into(option.targetView!!)
// }
// option.asGif -> {
// initNormalGifGlideRequest(option).transform(CircleCrop()).into(option.targetView!!)
// }
// option.asFile -> {
// initNormalFileGlideRequest(option).transform(CircleCrop()).into(option.targetView!!)
// }
// else -> {
// initNormalDrawableGlideRequest(option).transform(CircleCrop()).into(option.targetView!!)
// }
// }
// GlideApp.with(option.context).load(source(option)).transform(CircleCrop()).into(option.targetView!!)
// }
//
// /** 高斯模糊 */
// private fun loadBlur(option: ImageLoaderOption) {
// val list: MutableList<Transformation<Bitmap>> = ArrayList()
// list.add(BlurTransformation(25, 3))
//
// when {
// option.centerInsideEnable -> list.add(CenterInside())
// option.fitCenterEnable -> list.add(FitCenter())
// option.circleEnable -> list.add(CircleCrop()) //圆形
// }
//
// list.add(CenterCrop())
//
//
// val multiTransformation = MultiTransformation(list)
// GlideApp.with(option.context).load(source(option)).transform(multiTransformation).into(option.targetView!!)
// }


}

lib/common/src/main/java/com/suliang/common/util/image/ILoaderStrategy.kt → lib/common/src/main/java/com/suliang/common/util/image/IBaseLoaderStrategy.kt View File

@@ -1,17 +1,13 @@
package com.suliang.common.util.image

import android.net.Uri
import android.widget.ImageView
import java.io.File

/**
* author suliang
* create 2022/3/11 15:45
* Describe: 策略接口
*/
interface ILoaderStrategy {
interface IBaseLoaderStrategy {

fun loadImage(option : LoaderOptions)
fun loadImage(option : ImageLoaderOption)

/**
* 清理内存缓存

+ 30
- 22
lib/common/src/main/java/com/suliang/common/util/image/ImageLoader.kt View File

@@ -1,11 +1,8 @@
package com.suliang.common.util.image

import android.content.Context
import android.net.Uri
import android.widget.ImageView
import androidx.annotation.DrawableRes
import java.io.File
import java.net.URL

/**
* author suliang
@@ -21,43 +18,54 @@ import java.net.URL
* https://juejin.cn/post/6844903463134953479#heading-3
* https://www.jianshu.com/p/19420b151507
* https://blog.csdn.net/EthanCo/article/details/102587193
* https://www.jianshu.com/p/e26130a93289
*/
object ImageLoader : ILoaderStrategy {
object ImageLoader {

//具体实现的策略,外部可设置
private var mStrategy: ILoaderStrategy = GlideLoader()
var mStrategy: IBaseLoaderStrategy? = GlideLoaderStrategy()

public fun setMStrategy(strategy: ILoaderStrategy) {
this.mStrategy = mStrategy

fun loadImage(option: ImageLoaderOption) {
mStrategy?.loadImage(option)
}


fun loadImage(imageView: ImageView, url: String) {
loadImage(LoaderOptions(url).apply { targetView = imageView })
loadImage(ImageLoaderOption().apply {
this.url = url
targetView = imageView
})
}

fun loadImage(imageView: ImageView, file: File) {
loadImage( LoaderOptions(file = file).apply { targetView = imageView })
loadImage(ImageLoaderOption().apply {
this.file = file
targetView = imageView
})
}

fun loadImage(imageView: ImageView, drawableRes: Int) {
loadImage(LoaderOptions(drawableResId = drawableRes).apply { targetView = imageView })
fun loadImage(imageView: ImageView, resourceId: Int) {
loadImage(ImageLoaderOption().apply {
this.resourceId = resourceId
targetView = imageView
})
}

fun loadImage(imageView: ImageView, uri: Uri) {
loadImage(LoaderOptions(uri = uri).apply { targetView = imageView })
loadImage(ImageLoaderOption().apply {
this.uri = uri
targetView = imageView
})
}

override fun loadImage(option: LoaderOptions) {
mStrategy.loadImage(option)
}

// override fun clearMemoryCache() {
// mStrategyBase.clearMemoryCache()
// }
//
// override fun clearDiskCache() {
// mStrategyBase.clearDiskCache()
// }

override fun clearMemoryCache() {
mStrategy.clearMemoryCache()
}

override fun clearDiskCache() {
mStrategy.clearDiskCache()
}
}

+ 94
- 0
lib/common/src/main/java/com/suliang/common/util/image/ImageLoaderOption.kt View File

@@ -0,0 +1,94 @@
package com.suliang.common.util.image

import android.content.Context
import android.graphics.Bitmap
import android.graphics.drawable.Drawable
import android.net.Uri
import android.widget.ImageView
import androidx.annotation.DrawableRes
import com.bumptech.glide.Glide
import com.bumptech.glide.request.target.Target
import com.suliang.common.R
import java.io.File
import java.net.URL

/**
* author suliang
* create 2022/3/14 10:27
* Describe: 图片加载配置,所有配置信息都放入这里面
*/
class ImageLoaderOption {

//占位符
//选项: RequestBuilder、 RequestOption、
//变换: 改变加载的图片 Transformations 可以获取资源并修改它,然后返回被修改后的资源。通常变换操作是用来完成剪裁或对位图应用过滤器,但它也可以用于转换GIF动画,甚至自定义的资源类型。
// fitCenter() centerCrop() CircleCrop() transform(.....)
//目标: Target 是介于请求和请求者之间的中介者的角色。Target 负责展示占位符,加载资源,并为每个请求决定合适的尺寸

//过渡
//配置
//缓存
//资源重用




/** 上下文 */
var context : Context? = null
/** 目标view */
var targetView: ImageView? = null


/** 占位符是当请求正在执行时被展示的 Drawable 。*/
var placeholderResId: Int = 0
/** 错误符: 在请求永久性失败时展示。error Drawable 同样也在请求的url/model为 null ,且并没有设置 fallback Drawable 时展示*/
var errorResId: Int = 0
/** 后备回调符 : 在请求的url/model为 null 时展示 主要目的是允许用户指示 null 是否为可接受的正常情况*/
var fallback : Int = 0

//资源必须设置一样
var bitmap : Bitmap? = null
var drawable : Drawable ? = null
var url: String ? = null
var uri : Uri ? = null
var file : File ? = null
var resourceId : Int = 0
var byteArray : ByteArray ? = null

// var asDrawable : Boolean = true //默认
var asBitmap : Boolean = false
var asGif : Boolean = false
var asFile: Boolean = false


/**是否居中裁剪: 默认*/
// var centerCropEnable: Boolean = false
/** 居中全显 */
var centerInsideEnable: Boolean = false
var fitCenterEnable: Boolean = false

//圆角px值
var rounderCorners : Int = 0
//是否模糊
var blurEanble : Boolean = false
//是否圆形图片
var circleEnable : Boolean = false


//fitCenter
//RequestOption
//target
//后台 FutureTarget<Bitemap> f = Glide.with(context).asBitmap().load(url).submit(width,height); f.get() // Glide.with(context).clear(f)


// ImageView的自动变换
// 在Glide中,当你为一个 ImageView 开始加载时,Glide可能会自动应用 FitCenter 或 CenterCrop ,这取决于view的 ScaleType 。
// 如果 scaleType 是 CENTER_CROP , Glide 将会自动应用 CenterCrop 变换。
// 如果 scaleType 为 FIT_CENTER 或 CENTER_INSIDE ,Glide会自动使用 FitCenter 变换。
// 当然,你总有权利覆写默认的变换,只需要一个带有 Transformation 集合的 RequestOptions 即可。另外,你也可以通过使用 dontTransform() 确保不会自动应用任何变换。





}

+ 0
- 61
lib/common/src/main/java/com/suliang/common/util/image/LoaderOptions.kt View File

@@ -1,61 +0,0 @@
package com.suliang.common.util.image

import android.graphics.drawable.Drawable
import android.net.Uri
import android.widget.ImageView
import androidx.annotation.IdRes
import java.io.File
import java.net.URL

/**
* author suliang
* create 2022/3/11 15:45
* Describe: 加载配置
* 提取通用的View、加载路径等多参数
*/
class LoaderOptions @JvmOverloads constructor(var url: String? = null, var file: File? = null,
var drawableResId: Int = -1, var uri: Uri? = null) {

/** 预加载图 */
var placeholderResId: Int = -1
var placeHolderDrawable: Drawable? = null

/** 错误图 */
var errorResId: Int = -1

/**是否居中裁剪*/
var centerCropEnable: Boolean = false

/** 居中全显 */
var centerInsideEnable: Boolean = false

/**是否缓存到本地*/
var skipLocalCache: Boolean = false

var skipNetCache: Boolean = false

var targetWidth: Int = -1
var targetHeight: Int = -1

//圆角角度
var bitmapAngle: Float = -1f

//图片
var targetView: ImageView? = null

//回调
// var callBack: BitmapCallBack? = null


// fun into(view: ImageView) {
// this.targetView = view
// ImageLoader.loadImage(this)
// }

// fun bitmap(callBack: BitmapCallBack) {
// this.callBack = callBack
// ImageLoader.loadOption(this)
// }


}

+ 65
- 0
lib/common/src/main/java/com/suliang/common/util/image/MyGlideApp.kt View File

@@ -0,0 +1,65 @@
package com.suliang.common.util.image

import android.content.Context
import android.util.Log
import com.bumptech.glide.Glide
import com.bumptech.glide.GlideBuilder
import com.bumptech.glide.Registry
import com.bumptech.glide.annotation.GlideModule
import com.bumptech.glide.load.DecodeFormat
import com.bumptech.glide.load.engine.bitmap_recycle.LruBitmapPool
import com.bumptech.glide.load.engine.cache.InternalCacheDiskCacheFactory
import com.bumptech.glide.load.engine.cache.LruResourceCache
import com.bumptech.glide.load.engine.executor.GlideExecutor
import com.bumptech.glide.module.AppGlideModule
import com.bumptech.glide.module.LibraryGlideModule
import com.bumptech.glide.request.RequestOptions

/**
* author suliang
* create 2022/3/14 10:46
* Describe: Generated API 目前仅可以在 Application 模块内使用。这一限制可以让我们仅持有一份 Generated API,
* 而不是各个 Library 和 Application 中均有自己定义出来的 Generated API。
* 这一做法会让 Generated API 的调用更简单,并确保 Application 模块中 Generated API 调用的选项在各处行为一致。
* 这一限制在接下来的版本中也许会被取消(以实验性或其他的方式给出)
*
* 与 Glide.with() 不同,诸如 fitCenter() 和 placeholder() 等选项在 Builder 中直接可用,并不需要再传入单独的 RequestOptions 对象
*
* GlideApp.with(fragment).load(myUrl).placeholder(R.drawable.placeholder).fitCenter().into(imageView);
*
*
* https://blog.csdn.net/MldXTieJiang/article/details/109347774 全局配置
*/
@GlideModule
class MyGlideApp : AppGlideModule() {

//已经迁移到 Glide v4 的 AppGlideModule 和 LibraryGlideModule ,你可以完全禁用清单解析。这样可以改善 Glide 的初始启动时间,并避免尝试解析元数据时的一些潜在问题
override fun isManifestParsingEnabled(): Boolean {
return false
}

override fun applyOptions(context: Context, builder: GlideBuilder) {
builder.apply {

val cacheSize = Runtime.getRuntime().maxMemory() / 8
//设置Bitmap的缓存池
setBitmapPool(LruBitmapPool(30))
//设置内存缓存
setMemoryCache(LruResourceCache(cacheSize))
//设置磁盘缓存
setDiskCache(InternalCacheDiskCacheFactory(context))
//设置读取不在缓存中的资源的线程
setResizeExecutor(GlideExecutor.newSourceExecutor())
//设置读取磁盘缓存中的资源的线程
setDiskCacheExecutor(GlideExecutor.newDiskCacheExecutor())
//设置日子级别
setLogLevel(Log.DEBUG)
//设置全局选项
// val apply = RequestOptions().apply {
// format(DecodeFormat.PREFER_RGB_565)
// }
// setDefaultRequestOptions(apply)
}
}

}

Loading…
Cancel
Save