fix: 尝试优化 banner + svga 的内存占用, 添加资源回收逻辑
This commit is contained in:
@@ -59,9 +59,9 @@ public class RoomNormalListAdapter extends RecyclerView.Adapter<RoomNormalListAd
|
||||
|
||||
|
||||
if (UserModel.get().getCacheLoginUserInfo() != null && UserModel.get().getCacheLoginUserInfo().isSuperAdmin()) {
|
||||
OtherExtKt.setVis(holder.operationImg, true, false);
|
||||
OtherExtKt.setVis(holder.operationImg, false, false);
|
||||
} else {
|
||||
OtherExtKt.setVis(holder.operationImg,false,false);
|
||||
OtherExtKt.setVis(holder.operationImg,true,false);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -20,4 +20,7 @@ class HomeBannerAdapter : BaseBannerAdapter<BannerInfo?>() {
|
||||
val effectView = helper.findViewById<EffectView>(R.id.effectView)
|
||||
effectView.load(item?.bannerPic?:"",item?.fillVo?.imgMap,item?.fillVo?.textMap)
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
@@ -55,23 +55,26 @@ object AnimLoadUtil {
|
||||
}
|
||||
|
||||
fun isSvgaFile(path: String,callBack: (isSvga: Boolean,videoItem: SVGAVideoEntity?) -> Unit = {_,_->}){
|
||||
val inputStream = BufferedInputStream(FileInputStream(path))
|
||||
shareParser().decodeFromInputStream(
|
||||
inputStream,
|
||||
path,
|
||||
object : SVGAParser.ParseCompletion {
|
||||
override fun onComplete(videoItem: SVGAVideoEntity) {
|
||||
callBack(true,videoItem)
|
||||
}
|
||||
try {
|
||||
val inputStream = BufferedInputStream(FileInputStream(path))
|
||||
shareParser().decodeFromInputStream(
|
||||
inputStream,
|
||||
path,
|
||||
object : SVGAParser.ParseCompletion {
|
||||
override fun onComplete(videoItem: SVGAVideoEntity) {
|
||||
callBack(true,videoItem)
|
||||
}
|
||||
|
||||
override fun onError() {
|
||||
callBack(false,null)
|
||||
}
|
||||
},
|
||||
true,
|
||||
null,
|
||||
null
|
||||
)
|
||||
override fun onError() {
|
||||
callBack(false,null)
|
||||
}
|
||||
},
|
||||
true,
|
||||
null,
|
||||
null
|
||||
)
|
||||
} catch (e: Exception) {
|
||||
}
|
||||
}
|
||||
|
||||
//垃圾 不顶用
|
||||
|
@@ -20,6 +20,7 @@ import java.io.File
|
||||
object ResourceManager {
|
||||
|
||||
public var mClientResource : ClientResource? = null
|
||||
private val needLog = false;
|
||||
|
||||
fun initResource() {
|
||||
InitialModel.get().clientResource().doOnSuccess {
|
||||
@@ -73,7 +74,7 @@ object ResourceManager {
|
||||
|
||||
private fun doLoad(url: String) {
|
||||
if (url.isVerify()) {
|
||||
"预加载 -> ResourceManager doLoad url = $url".doLog()
|
||||
"预加载 -> ResourceManager doLoad url = $url".doLog(needLog)
|
||||
GlideUtils.instance().downloadFromUrl2(AppUtils.getApp(),url,object : RequestListener<File?> {
|
||||
override fun onLoadFailed(
|
||||
e: GlideException?,
|
||||
@@ -81,7 +82,7 @@ object ResourceManager {
|
||||
target: Target<File?>?,
|
||||
isFirstResource: Boolean
|
||||
): Boolean {
|
||||
"预加载 -> ResourceManager onLoadFailed error = ${e?.message} url = $url".doLog()
|
||||
"预加载 -> ResourceManager onLoadFailed error = ${e?.message} url = $url".doLog(needLog)
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -92,7 +93,7 @@ object ResourceManager {
|
||||
dataSource: DataSource?,
|
||||
isFirstResource: Boolean
|
||||
): Boolean {
|
||||
"预加载 -> ResourceManager onResourceReady Success url = $url".doLog()
|
||||
"预加载 -> ResourceManager onResourceReady Success url = $url".doLog(needLog)
|
||||
return true
|
||||
}
|
||||
})
|
||||
|
@@ -13,6 +13,7 @@ import android.text.StaticLayout
|
||||
import android.text.TextPaint
|
||||
import android.text.TextUtils
|
||||
import android.util.AttributeSet
|
||||
import android.util.LruCache
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.FrameLayout
|
||||
@@ -37,6 +38,7 @@ import com.netease.nim.uikit.support.glide.GlideApp
|
||||
import com.opensource.svgaplayer.SVGACallback
|
||||
import com.opensource.svgaplayer.SVGADrawable
|
||||
import com.opensource.svgaplayer.SVGADynamicEntity
|
||||
import com.opensource.svgaplayer.SVGAImageView
|
||||
import com.opensource.svgaplayer.SVGAParser
|
||||
import com.opensource.svgaplayer.SVGAParser.Companion.shareParser
|
||||
import com.opensource.svgaplayer.SVGAVideoEntity
|
||||
@@ -60,6 +62,7 @@ class EffectView : FrameLayout {
|
||||
|
||||
var mCallBack : CallBack? = null
|
||||
var hasAnimImg = false; // 图片是否可能带 序列帧动图
|
||||
var mPlayerCount = 1;
|
||||
|
||||
private var mResourceUrl = ""
|
||||
private var mEffectType = EffectType.IMG
|
||||
@@ -71,6 +74,10 @@ class EffectView : FrameLayout {
|
||||
|
||||
private var mNeedLog = false
|
||||
|
||||
private var mImage : ImageView? = null
|
||||
private var mSvga : SVGAView? = null
|
||||
private var mVap : AnimView? = null
|
||||
|
||||
private fun init(context: Context) {
|
||||
|
||||
}
|
||||
@@ -119,7 +126,7 @@ class EffectView : FrameLayout {
|
||||
} else {
|
||||
loadEffect(EffectType.MP4,resource)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@@ -153,14 +160,8 @@ class EffectView : FrameLayout {
|
||||
private fun loadImg(resource: File) {
|
||||
"EffectView loadImg() ".doLog(mNeedLog)
|
||||
try {
|
||||
val imageView = ImageView(context)
|
||||
this@EffectView.addView(imageView)
|
||||
imageView.setViewWH(
|
||||
ViewGroup.LayoutParams.MATCH_PARENT,
|
||||
ViewGroup.LayoutParams.MATCH_PARENT,
|
||||
false
|
||||
)
|
||||
imageView.scaleType = ImageView.ScaleType.FIT_XY
|
||||
val imageView = createImageView()
|
||||
mImage = imageView
|
||||
|
||||
Glide.with(this)
|
||||
.asBitmap()
|
||||
@@ -189,26 +190,8 @@ class EffectView : FrameLayout {
|
||||
imageView?.post {
|
||||
if (!imageView.isAttachedToWindow) return@post
|
||||
resource?.let {
|
||||
if (hasAnimImg) {
|
||||
val split: List<Drawable> = split(it)
|
||||
if (split.isVerify()) {
|
||||
val animationDrawable = AnimationDrawable()
|
||||
for (i in split.indices) {
|
||||
animationDrawable.addFrame(split[i], 200)
|
||||
}
|
||||
imageView.setImageDrawable(animationDrawable)
|
||||
animationDrawable.isOneShot = false
|
||||
animationDrawable.start()
|
||||
} else {
|
||||
imageView.setImageBitmap(it)
|
||||
}
|
||||
"EffectView loadImg() start".doLog(mNeedLog)
|
||||
playCallBack(true)
|
||||
} else {
|
||||
"EffectView loadImg() start".doLog(mNeedLog)
|
||||
playCallBack(true)
|
||||
imageView.setImageBitmap(it)
|
||||
}
|
||||
mCallBack?.onCache(resource)
|
||||
imgResourceLoad(imageView,resource)
|
||||
}
|
||||
}
|
||||
return true
|
||||
@@ -221,15 +204,48 @@ class EffectView : FrameLayout {
|
||||
}
|
||||
|
||||
}
|
||||
private fun createImageView() : ImageView {
|
||||
val imageView = ImageView(context)
|
||||
this@EffectView.addView(imageView)
|
||||
imageView.setViewWH(
|
||||
ViewGroup.LayoutParams.MATCH_PARENT,
|
||||
ViewGroup.LayoutParams.MATCH_PARENT,
|
||||
false
|
||||
)
|
||||
imageView.scaleType = ImageView.ScaleType.FIT_XY
|
||||
return imageView
|
||||
}
|
||||
private fun imgResourceLoad(imageView: ImageView, resource: Bitmap) {
|
||||
if (hasAnimImg) {
|
||||
val split: List<Drawable> = split(resource)
|
||||
if (split.isVerify()) {
|
||||
val animationDrawable = AnimationDrawable()
|
||||
for (i in split.indices) {
|
||||
animationDrawable.addFrame(split[i], 200)
|
||||
}
|
||||
imageView.setImageDrawable(animationDrawable)
|
||||
animationDrawable.isOneShot = false
|
||||
animationDrawable.start()
|
||||
} else {
|
||||
imageView.setImageBitmap(resource)
|
||||
}
|
||||
"EffectView loadImg() start".doLog(mNeedLog)
|
||||
playCallBack(true)
|
||||
} else {
|
||||
"EffectView loadImg() start".doLog(mNeedLog)
|
||||
playCallBack(true)
|
||||
imageView.setImageBitmap(resource)
|
||||
}
|
||||
}
|
||||
|
||||
private fun loadMp4(resource: File) {
|
||||
"EffectView loadMp4() ".doLog(mNeedLog)
|
||||
try {
|
||||
val animView = AnimView(context)
|
||||
mVap = animView
|
||||
animView.setLoop(mPlayerCount)
|
||||
this@EffectView.addView(animView)
|
||||
animView.setViewWH(ViewGroup.LayoutParams.MATCH_PARENT,ViewGroup.LayoutParams.MATCH_PARENT,false)
|
||||
// AnimView.setLoop(Int.MAX_VALUE)
|
||||
// AnimView.setScaleType(ScaleType.FIT_XY)
|
||||
animView.setAnimListener(object : IAnimListener {
|
||||
override fun onFailed(errorType: Int, errorMsg: String?) {
|
||||
playCallBack(false)
|
||||
@@ -326,6 +342,10 @@ class EffectView : FrameLayout {
|
||||
resources?.forEach {
|
||||
it?.bitmap?.recycle()
|
||||
}
|
||||
|
||||
bitmapMap?.forEach { t, u ->
|
||||
u?.recycle()
|
||||
}
|
||||
}
|
||||
})
|
||||
animView.startPlay(resource)
|
||||
@@ -375,23 +395,15 @@ class EffectView : FrameLayout {
|
||||
private fun loadSvga(resource: File) {
|
||||
"EffectView loadSvga() ".doLog(mNeedLog)
|
||||
try {
|
||||
val svgaView = SVGAView(context)
|
||||
this@EffectView.addView(svgaView)
|
||||
svgaView.setViewWH(ViewGroup.LayoutParams.MATCH_PARENT,ViewGroup.LayoutParams.MATCH_PARENT,false)
|
||||
svgaView.scaleType = ImageView.ScaleType.FIT_XY
|
||||
val svgaView = createSvgaView()
|
||||
mSvga = svgaView
|
||||
val inputStream = BufferedInputStream(FileInputStream(resource.path))
|
||||
shareParser().decodeFromInputStream(
|
||||
inputStream,
|
||||
resource.path,
|
||||
object : SVGAParser.ParseCompletion {
|
||||
override fun onComplete(videoItem: SVGAVideoEntity) {
|
||||
svgaView.post {
|
||||
if (!svgaView.isAttachedToWindow) return@post
|
||||
svgaView.setImageDrawable(SVGADrawable(videoItem))
|
||||
svgaView.startAnimation()
|
||||
playCallBack(true)
|
||||
"EffectView loadSvga() true".doLog(mNeedLog)
|
||||
}
|
||||
playSvga(svgaView,videoItem)
|
||||
}
|
||||
|
||||
override fun onError() {
|
||||
@@ -419,27 +431,8 @@ class EffectView : FrameLayout {
|
||||
return
|
||||
}
|
||||
|
||||
val svgaView = SVGAView(context)
|
||||
this@EffectView.addView(svgaView)
|
||||
svgaView.setViewWH(ViewGroup.LayoutParams.MATCH_PARENT,ViewGroup.LayoutParams.MATCH_PARENT,false)
|
||||
svgaView.scaleType = ImageView.ScaleType.FIT_XY
|
||||
svgaView.callback = object : SVGACallback {
|
||||
override fun onPause() {
|
||||
"EffectView loadSvga() SVGACallback onPause()".doLog(mNeedLog)
|
||||
}
|
||||
|
||||
override fun onFinished() {
|
||||
"EffectView loadSvga() SVGACallback onFinished()".doLog(mNeedLog)
|
||||
}
|
||||
|
||||
override fun onRepeat() {
|
||||
// "EffectView loadSvga() SVGACallback onRepeat()".doLog(mNeedLog)
|
||||
}
|
||||
|
||||
override fun onStep(i: Int, v: Double) {
|
||||
}
|
||||
}
|
||||
|
||||
val svgaView = createSvgaView()
|
||||
mSvga = svgaView
|
||||
val dynamicEntity = SVGADynamicEntity()
|
||||
|
||||
if (mTextMap?.isNotEmpty() == true) {
|
||||
@@ -498,14 +491,6 @@ class EffectView : FrameLayout {
|
||||
}
|
||||
}
|
||||
|
||||
private fun playCallBack(isSuccess: Boolean,type: Int? = -1) {
|
||||
if (isSuccess) {
|
||||
"EffectView playCallBack() 加载成功 url = $mResourceUrl".doLog(mNeedLog)
|
||||
} else {
|
||||
"EffectView playCallBack() 加载失败 url = $mResourceUrl".doLog(mNeedLog)
|
||||
}
|
||||
mCallBack?.onPlay(isSuccess,type)
|
||||
}
|
||||
|
||||
private fun split(bitmap: Bitmap?): List<Drawable> {
|
||||
"EffectView split() ".doLog(mNeedLog)
|
||||
@@ -580,24 +565,108 @@ class EffectView : FrameLayout {
|
||||
.submit()
|
||||
}
|
||||
|
||||
private fun playSvga(svgaView:SVGAView,videoItem: SVGAVideoEntity,dynamicEntity: SVGADynamicEntity) {
|
||||
val drawable = SVGADrawable(videoItem, dynamicEntity)
|
||||
|
||||
private fun createSvgaView() :SVGAView{
|
||||
val svgaView = SVGAView(context)
|
||||
this@EffectView.addView(svgaView)
|
||||
svgaView.setViewWH(ViewGroup.LayoutParams.MATCH_PARENT,ViewGroup.LayoutParams.MATCH_PARENT,false)
|
||||
svgaView.scaleType = ImageView.ScaleType.FIT_XY
|
||||
svgaView.loops = mPlayerCount
|
||||
svgaView.fillMode = SVGAImageView.FillMode.Forward
|
||||
svgaView.callback = object : SVGACallback {
|
||||
override fun onPause() {
|
||||
"EffectView loadSvga() SVGACallback onPause()".doLog(mNeedLog)
|
||||
}
|
||||
|
||||
override fun onFinished() {
|
||||
"EffectView loadSvga() SVGACallback onFinished()".doLog(mNeedLog)
|
||||
}
|
||||
|
||||
override fun onRepeat() {
|
||||
// "EffectView loadSvga() SVGACallback onRepeat()".doLog(mNeedLog)
|
||||
}
|
||||
|
||||
override fun onStep(i: Int, v: Double) {
|
||||
}
|
||||
}
|
||||
return svgaView
|
||||
}
|
||||
private fun playSvga(svgaView:SVGAView,videoItem: SVGAVideoEntity,dynamicEntity: SVGADynamicEntity?=null) {
|
||||
val drawable = if (dynamicEntity != null) SVGADrawable(videoItem, dynamicEntity) else SVGADrawable(videoItem)
|
||||
mCallBack?.onCache(drawable)
|
||||
svgaView.post {
|
||||
if (!svgaView.isAttachedToWindow) return@post
|
||||
svgaView.setImageDrawable(drawable)
|
||||
svgaView.stepToFrame(0, true)
|
||||
playCallBack(true)
|
||||
"EffectView loadSvga() start".doLog(mNeedLog)
|
||||
"EffectView playSvga() start".doLog(mNeedLog)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public fun loadUrlForCache() {
|
||||
|
||||
}
|
||||
|
||||
|
||||
public fun setTextView(textSize: Float) {
|
||||
mTextSize = textSize
|
||||
}
|
||||
|
||||
public interface CallBack{
|
||||
fun onPlay(isSuccess: Boolean,type: Int? = -1)
|
||||
private fun playCallBack(isSuccess: Boolean,type: Int? = -1) {
|
||||
if (isSuccess) {
|
||||
"EffectView playCallBack() 加载成功 url = $mResourceUrl".doLog(mNeedLog)
|
||||
} else {
|
||||
"EffectView playCallBack() 加载失败 url = $mResourceUrl".doLog(mNeedLog)
|
||||
}
|
||||
mCallBack?.onPlay(isSuccess,type)
|
||||
}
|
||||
|
||||
|
||||
override fun onDetachedFromWindow() {
|
||||
super.onDetachedFromWindow()
|
||||
"EffectView 被销毁了 $mResourceUrl".doLog()
|
||||
|
||||
try {
|
||||
mImage?.setImageBitmap(null)
|
||||
mImage = null
|
||||
|
||||
mSvga?.pauseAnimation()
|
||||
mSvga?.stopAnimation()
|
||||
mSvga?.clearAnimation()
|
||||
mSvga?.clear()
|
||||
mSvga = null
|
||||
|
||||
mVap?.stopPlay()
|
||||
mVap?.clearAnimation()
|
||||
mVap=null
|
||||
|
||||
removeAllViews()
|
||||
} catch (e: Exception) {
|
||||
"EffectView 被销毁了,回收资源异常 ${e.message}".doLog()
|
||||
}
|
||||
}
|
||||
|
||||
public interface CallBack{
|
||||
fun onPlay(isSuccess: Boolean,type: Int? = -1)
|
||||
fun onCache(resource:Any){};
|
||||
}
|
||||
|
||||
|
||||
|
||||
class EffectLruCache(maxSize: Int){
|
||||
val mLruCache = LruCache<String, Any>(maxSize)
|
||||
fun get(key: String): Any? {
|
||||
return mLruCache.get(key)
|
||||
}
|
||||
|
||||
fun put(key: String, entity: Any) {
|
||||
mLruCache.put(key, entity)
|
||||
}
|
||||
|
||||
fun clear() {
|
||||
mLruCache.evictAll()
|
||||
}
|
||||
}
|
||||
|
||||
}
|
Binary file not shown.
Before Width: | Height: | Size: 1.7 KiB |
@@ -882,16 +882,21 @@ public class GiftModel extends BaseModel implements IGiftModel {
|
||||
|
||||
@Override
|
||||
public void handleMessage(Message msg) {
|
||||
GiftModel giftModel = mReference.get();
|
||||
if (giftModel == null) return;
|
||||
super.handleMessage(msg);
|
||||
if (giftModel.giftQueue.size() > 0) {
|
||||
CustomAttachment attachment = giftModel.giftQueue.remove(0);
|
||||
if (attachment != null)
|
||||
giftModel.parseChatRoomAttachment(attachment);
|
||||
GiftModel giftModel = null;
|
||||
try {
|
||||
giftModel = mReference.get();
|
||||
if (giftModel == null) return;
|
||||
super.handleMessage(msg);
|
||||
if (giftModel.giftQueue.size() > 0) {
|
||||
CustomAttachment attachment = giftModel.giftQueue.remove(0);
|
||||
if (attachment != null)
|
||||
giftModel.parseChatRoomAttachment(attachment);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
OtherExtKt.doLog(" 礼物消息异常 : "+e.getMessage());
|
||||
}
|
||||
|
||||
if (giftModel.giftQueue.size() > 0) {
|
||||
if (giftModel != null && !giftModel.giftQueue.isEmpty()) {
|
||||
sendEmptyMessageDelayed(0, 150);
|
||||
}
|
||||
}
|
||||
|
@@ -2944,7 +2944,7 @@ public final class IMNetEaseManager {
|
||||
carAttachment.effect = carInfo.getEffect();
|
||||
carAttachment.viewUrl = carInfo.getViewUrl();
|
||||
carAttachment.otherViewType = carInfo.getOtherViewType();
|
||||
|
||||
OtherExtKt.doLog(" 座驾 , 发送 座驾消息 播放动画");
|
||||
ChatRoomMessage message = ChatRoomMessageBuilder.createChatRoomCustomMessage(
|
||||
String.valueOf(roomInfo.getRoomId()), carAttachment);
|
||||
e.onSuccess(message);
|
||||
|
@@ -267,7 +267,7 @@ class SVGAView : SVGAImageView, ILog {
|
||||
logD("SVGAView parseCompletion onComplete url:$url")
|
||||
if (resourceUrl != url) {
|
||||
return
|
||||
}
|
||||
}
|
||||
svgaCache?.put(resourceUrl ?: "", videoItem)
|
||||
this@SVGAView.post {
|
||||
this@SVGAView.setImageDrawable(SVGADrawable(videoItem))
|
||||
|
Reference in New Issue
Block a user