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

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

import android.os.Bundle import android.os.Bundle
import android.os.Looper import android.os.Looper
import android.view.View import android.view.View
import com.bumptech.glide.load.resource.bitmap.CircleCrop
import com.suliang.common.base.activity.BaseActivity import com.suliang.common.base.activity.BaseActivity
import com.suliang.common.util.LogUtil import com.suliang.common.util.LogUtil
import com.suliang.common.util.image.ImageLoader 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.*
import com.suliang.common.util.media.MPManager.addPlayListener
import com.suliang.common.util.thread.AppExecutors
import com.xkl.cdl.R import com.xkl.cdl.R
import com.xkl.cdl.databinding.ActivitySplashBinding import com.xkl.cdl.databinding.ActivitySplashBinding






override fun loadData() { 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 { val util:IMP = MPManager.apply {

+ 3
- 1
build.gradle View File

appcompat_version: "1.4.1", appcompat_version: "1.4.1",
material_version : "1.3.0", material_version : "1.3.0",
lifecycle_version: "2.5.0-alpha02", lifecycle_version: "2.5.0-alpha02",
glide_version : "4.1.0",
glide_version : "4.11.0",
] ]
//必须依赖 //必须依赖
dependencies_required = [ dependencies_required = [
//Glide 依赖和配置 //Glide 依赖和配置
Glide : "com.github.bumptech.glide:glide:${versions.glide_version}", Glide : "com.github.bumptech.glide:glide:${versions.glide_version}",
GlideCompiler : "com.github.bumptech.glide:compiler:${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

rootProject.ext.dependencies_required.each{ k,v -> implementation v} rootProject.ext.dependencies_required.each{ k,v -> implementation v}
testImplementation rootProject.ext.dependencies_testImplementation.junit testImplementation rootProject.ext.dependencies_testImplementation.junit
rootProject.ext.dependencies_androidTestImplementation.each{ k,v -> androidTestImplementation v} 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 //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



# If you keep the line number information, uncomment this to # If you keep the line number information, uncomment this to
# hide the original source file name. # 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

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

<!--网络权限-->
<uses-permission android:name="android.permission.INTERNET"/> <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连接,否则连接失败 <!--networkSecurityConfig,usesCleartextTraffic 二选一都可以9.0-P以上高版本的http连接,否则连接失败
android:networkSecurityConfig="@xml/network_security_config" android:networkSecurityConfig="@xml/network_security_config"
android:usesCleartextTraffic="true" android:usesCleartextTraffic="true"

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

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

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

package com.suliang.common.util.image package com.suliang.common.util.image


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

/** /**
* author suliang * author suliang
* create 2022/3/11 15:45 * create 2022/3/11 15:45
* Describe: 策略接口 * 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

package com.suliang.common.util.image package com.suliang.common.util.image


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


/** /**
* author suliang * author suliang
* https://juejin.cn/post/6844903463134953479#heading-3 * https://juejin.cn/post/6844903463134953479#heading-3
* https://www.jianshu.com/p/19420b151507 * https://www.jianshu.com/p/19420b151507
* https://blog.csdn.net/EthanCo/article/details/102587193 * 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) { 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) { 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) { 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

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

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

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