/*
* Copyright (C) 2017 Peng fei Pan <sky@xiaopan.me>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package me.xiaopan.sketch.drawable;
import android.content.ContentResolver;
import android.content.res.AssetFileDescriptor;
import android.content.res.AssetManager;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.net.Uri;
import android.support.annotation.NonNull;
import java.io.File;
import java.io.FileDescriptor;
import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteBuffer;
import java.util.HashMap;
import java.util.Map;
import me.xiaopan.sketch.cache.BitmapPool;
import me.xiaopan.sketch.cache.BitmapPoolUtils;
import me.xiaopan.sketch.request.ImageFrom;
import me.xiaopan.sketch.util.SketchUtils;
import pl.droidsonroids.gif.GifDrawable;
/**
* 增加了从BitmapPool中寻找可复用Bitmap的功能以及图片的信息
*/
// SketchGifDrawableImpl类配置了混淆时忽略警告,以后内部类有变化时需要同步调整混淆配置,并打包验证
public class SketchGifDrawableImpl extends GifDrawable implements SketchGifDrawable {
protected String logName = "SketchGifDrawable";
private String key;
private String uri;
private ImageAttrs imageAttrs;
private ImageFrom imageFrom;
private BitmapPool bitmapPool;
private Map<AnimationListener, pl.droidsonroids.gif.AnimationListener> listenerMap;
SketchGifDrawableImpl(String key, String uri, ImageAttrs imageAttrs, BitmapPool bitmapPool,
AssetFileDescriptor afd) throws IOException {
super(afd);
this.key = key;
this.uri = uri;
this.imageAttrs = imageAttrs;
this.bitmapPool = bitmapPool;
}
SketchGifDrawableImpl(String key, String uri, ImageAttrs imageAttrs, BitmapPool bitmapPool,
AssetManager assets, String assetName) throws IOException {
super(assets, assetName);
this.key = key;
this.uri = uri;
this.imageAttrs = imageAttrs;
this.bitmapPool = bitmapPool;
}
SketchGifDrawableImpl(String key, String uri, ImageAttrs imageAttrs, BitmapPool bitmapPool,
ByteBuffer buffer) throws IOException {
super(buffer);
this.key = key;
this.uri = uri;
this.imageAttrs = imageAttrs;
this.bitmapPool = bitmapPool;
}
SketchGifDrawableImpl(String key, String uri, ImageAttrs imageAttrs, BitmapPool bitmapPool,
byte[] bytes) throws IOException {
super(bytes);
this.key = key;
this.uri = uri;
this.imageAttrs = imageAttrs;
this.bitmapPool = bitmapPool;
}
SketchGifDrawableImpl(String key, String uri, ImageAttrs imageAttrs, BitmapPool bitmapPool,
FileDescriptor fd) throws IOException {
super(fd);
this.key = key;
this.uri = uri;
this.imageAttrs = imageAttrs;
this.bitmapPool = bitmapPool;
}
SketchGifDrawableImpl(String key, String uri, ImageAttrs imageAttrs, BitmapPool bitmapPool,
File file) throws IOException {
super(file);
this.key = key;
this.uri = uri;
this.imageAttrs = imageAttrs;
this.bitmapPool = bitmapPool;
}
SketchGifDrawableImpl(String key, String uri, ImageAttrs imageAttrs, BitmapPool bitmapPool,
String filePath) throws IOException {
super(filePath);
this.key = key;
this.uri = uri;
this.imageAttrs = imageAttrs;
this.bitmapPool = bitmapPool;
}
SketchGifDrawableImpl(String key, String uri, ImageAttrs imageAttrs, BitmapPool bitmapPool,
Resources res, int id) throws Resources.NotFoundException, IOException {
super(res, id);
this.key = key;
this.uri = uri;
this.imageAttrs = imageAttrs;
this.bitmapPool = bitmapPool;
}
SketchGifDrawableImpl(String key, String imageUri, ImageAttrs imageAttrs, BitmapPool bitmapPool,
ContentResolver resolver, Uri uri) throws IOException {
super(resolver, uri);
this.key = key;
this.uri = imageUri;
this.imageAttrs = imageAttrs;
this.bitmapPool = bitmapPool;
}
SketchGifDrawableImpl(String key, String uri, ImageAttrs imageAttrs, BitmapPool bitmapPool,
InputStream stream) throws IOException {
super(stream);
this.key = key;
this.uri = uri;
this.imageAttrs = imageAttrs;
this.bitmapPool = bitmapPool;
}
@Override
protected Bitmap makeBitmap(int width, int height, Bitmap.Config config) {
if (bitmapPool != null) {
return bitmapPool.getOrMake(width, height, config);
}
return super.makeBitmap(width, height, config);
}
@Override
protected void recycleBitmap() {
if (mBuffer == null) {
return;
}
if (bitmapPool != null) {
BitmapPoolUtils.freeBitmapToPool(mBuffer, bitmapPool);
} else {
super.recycleBitmap();
}
}
@Override
public String getKey() {
return key;
}
@Override
public String getUri() {
return uri;
}
@Override
public int getOriginWidth() {
return imageAttrs.getOriginWidth();
}
@Override
public int getOriginHeight() {
return imageAttrs.getOriginHeight();
}
@Override
public String getMimeType() {
return imageAttrs.getMimeType();
}
@Override
public int getOrientation() {
return imageAttrs.getOrientation();
}
@Override
public ImageFrom getImageFrom() {
return imageFrom;
}
@Override
public void setImageFrom(ImageFrom imageFrom) {
this.imageFrom = imageFrom;
}
@Override
public String getInfo() {
return SketchUtils.makeImageInfo(logName, mBuffer, imageAttrs.getMimeType(), getAllocationByteCount());
}
@Override
public int getByteCount() {
return (int) getAllocationByteCount();
}
@Override
public Bitmap.Config getBitmapConfig() {
return mBuffer != null ? mBuffer.getConfig() : null;
}
@Override
public void addAnimationListener(@NonNull final AnimationListener listener) {
if (listenerMap == null) {
listenerMap = new HashMap<AnimationListener, pl.droidsonroids.gif.AnimationListener>();
}
// 这个内部类配置了混淆时忽略警告,以后有变化时需要同步调整混淆配置,并打包验证
pl.droidsonroids.gif.AnimationListener animationListener = new pl.droidsonroids.gif.AnimationListener() {
@Override
public void onAnimationCompleted(int loopNumber) {
listener.onAnimationCompleted(loopNumber);
}
};
addAnimationListener(animationListener);
listenerMap.put(listener, animationListener);
}
@Override
public boolean removeAnimationListener(AnimationListener listener) {
if (listenerMap == null || listenerMap.isEmpty()) {
return false;
}
pl.droidsonroids.gif.AnimationListener animationListener = listenerMap.remove(listener);
return animationListener != null && removeAnimationListener(animationListener);
}
@Override
public void followPageVisible(boolean userVisible, boolean fromDisplayCompleted) {
if (userVisible) {
start();
} else {
if (fromDisplayCompleted) {
// 图片加载完了,但是页面还不可见的时候就停留着在第一帧
seekToFrame(0);
stop();
} else {
stop();
}
}
}
}