/*
* Copyright (C) 2013 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.feature;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.LayerDrawable;
import me.xiaopan.sketch.SketchImageView;
import me.xiaopan.sketch.drawable.LoadingDrawable;
import me.xiaopan.sketch.drawable.RefDrawable;
import me.xiaopan.sketch.drawable.SketchDrawable;
import me.xiaopan.sketch.drawable.SketchGifDrawable;
import me.xiaopan.sketch.request.CancelCause;
import me.xiaopan.sketch.request.DisplayOptions;
import me.xiaopan.sketch.request.DisplayParams;
import me.xiaopan.sketch.request.DisplayRequest;
import me.xiaopan.sketch.request.ImageViewInterface;
import me.xiaopan.sketch.util.SketchUtils;
/**
* 请求基本功能,更新图片显示引用计数和在onDetachedFromWindow的时候取消请求并清空图片
*/
public class RequestFunction extends SketchImageView.Function {
private ImageViewInterface imageViewInterface;
private DisplayOptions displayOptions = new DisplayOptions();
private DisplayParams displayParams;
private boolean oldDrawableFromSketch;
private boolean newDrawableFromSketch;
public RequestFunction(ImageViewInterface imageViewInterface) {
this.imageViewInterface = imageViewInterface;
}
/**
* 修改Drawable显示状态
*
* @param callingStation 调用位置
* @param drawable Drawable
* @param isDisplayed 是否已显示
* @return true:drawable或其子Drawable是SketchDrawable
*/
private static boolean notifyDrawable(String callingStation, Drawable drawable, final boolean isDisplayed) {
boolean isSketchDrawable = false;
if (drawable != null) {
if (drawable instanceof LayerDrawable) {
LayerDrawable layerDrawable = (LayerDrawable) drawable;
for (int i = 0, z = layerDrawable.getNumberOfLayers(); i < z; i++) {
isSketchDrawable |= notifyDrawable(callingStation, layerDrawable.getDrawable(i), isDisplayed);
}
} else {
if (!isDisplayed && drawable instanceof LoadingDrawable) {
LoadingDrawable loadingDrawable = (LoadingDrawable) drawable;
DisplayRequest displayRequest = loadingDrawable.getRequest();
if (displayRequest != null && !displayRequest.isFinished()) {
displayRequest.cancel(CancelCause.BE_REPLACED_ON_SET_DRAWABLE);
}
}
if (drawable instanceof RefDrawable) {
((RefDrawable) drawable).setIsDisplayed(callingStation, isDisplayed);
} else if (drawable instanceof SketchGifDrawable) {
if (!isDisplayed) {
((SketchGifDrawable) drawable).recycle();
}
}
isSketchDrawable = drawable instanceof SketchDrawable;
}
}
return isSketchDrawable;
}
@Override
public boolean onDetachedFromWindow() {
// 主动取消请求
DisplayRequest potentialRequest = SketchUtils.findDisplayRequest(imageViewInterface);
if (potentialRequest != null && !potentialRequest.isFinished()) {
potentialRequest.cancel(CancelCause.ON_DETACHED_FROM_WINDOW);
}
// 如果当前图片是来自Sketch,那么就有可能在这里被主动回收,因此要主动设置ImageView的drawable为null
final Drawable oldDrawable = imageViewInterface.getDrawable();
return oldDrawable != null && notifyDrawable("onDetachedFromWindow", oldDrawable, false);
}
@Override
public boolean onDrawableChanged(String callPosition, Drawable oldDrawable, Drawable newDrawable) {
// 当Drawable改变的时候新Drawable的显示引用计数加1,旧Drawable的显示引用计数减1,一定要先处理newDrawable
newDrawableFromSketch = notifyDrawable(callPosition + ":newDrawable", newDrawable, true);
oldDrawableFromSketch = notifyDrawable(callPosition + ":oldDrawable", oldDrawable, false);
// 如果新Drawable不是来自Sketch,那么就要清空显示参数,防止被RecyclerCompatFunction在onAttachedToWindow的时候错误的恢复成上一张图片
if (!newDrawableFromSketch) {
displayParams = null;
}
return false;
}
public DisplayParams getDisplayParams() {
return displayParams;
}
public void setDisplayParams(DisplayParams displayParams) {
this.displayParams = displayParams;
}
@SuppressWarnings("unused")
public boolean isOldDrawableFromSketch() {
return oldDrawableFromSketch;
}
public boolean isNewDrawableFromSketch() {
return newDrawableFromSketch;
}
public DisplayOptions getDisplayOptions() {
return displayOptions;
}
}