提交 da4ce795 编写于 作者: S Sam Judd

Improve thumbnail performance.

上级 4a5c5613
......@@ -5,6 +5,7 @@ import android.widget.ImageView;
import com.bumptech.glide.request.GlideAnimation;
public class DrawableImageViewTarget extends ViewTarget<ImageView, Drawable> {
private static final float SQUARE_RATIO_MARGIN = 0.05f;
private final ImageView view;
public DrawableImageViewTarget(ImageView view) {
......@@ -14,6 +15,19 @@ public class DrawableImageViewTarget extends ViewTarget<ImageView, Drawable> {
@Override
public void onResourceReady(Drawable resource, GlideAnimation<Drawable> animation) {
//TODO: Try to generalize this to other sizes/shapes.
// This is a dirty hack that tries to make loading square thumbnails and then square full images less costly by
// forcing both the smaller thumb and the larger version to have exactly the same intrinsic dimensions. If a
// drawable is replaced in an ImageView by another drawable with different intrinsic dimensions, the ImageView
// requests a layout. Scrolling rapidly while replacing thumbs with larger images triggers lots of these calls
// and causes significant amounts of jank.
float viewRatio = view.getWidth() / (float) view.getHeight();
float drawableRatio = resource.getIntrinsicWidth() / (float) resource.getIntrinsicHeight();
if (Math.abs(viewRatio - 1f) <= SQUARE_RATIO_MARGIN && Math.abs(drawableRatio - 1f) <= SQUARE_RATIO_MARGIN) {
resource = new SquaringDrawable(resource, view.getWidth());
}
if (animation == null || !animation.animate(view.getDrawable(), resource, view, this)) {
view.setImageDrawable(resource);
}
......
package com.bumptech.glide.request.target;
import android.annotation.TargetApi;
import android.graphics.Canvas;
import android.graphics.ColorFilter;
import android.graphics.PorterDuff;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
/**
* A wrapper drawable to square the wrapped drawable so that it expands to fill a square with exactly the given side
* length. The goal of this drawable is to ensure that square thumbnail drawables always match the size of the view
* they will be displayed in to avoid a costly requestLayout call. This class should not be used with views or drawables
* that are not square.
*/
public class SquaringDrawable extends Drawable {
private final Drawable wrapped;
private int side;
public SquaringDrawable(Drawable wrapped, int side) {
this.wrapped = wrapped;
this.side = side;
}
@Override
public void setBounds(int left, int top, int right, int bottom) {
super.setBounds(left, top, right, bottom);
wrapped.setBounds(left, top, right, bottom);
}
@Override
public void setBounds(Rect bounds) {
super.setBounds(bounds);
wrapped.setBounds(bounds);
}
public void setChangingConfigurations(int configs) {
wrapped.setChangingConfigurations(configs);
}
@Override
public int getChangingConfigurations() {
return wrapped.getChangingConfigurations();
}
@Override
public void setDither(boolean dither) {
wrapped.setDither(dither);
}
@Override
public void setFilterBitmap(boolean filter) {
wrapped.setFilterBitmap(filter);
}
@TargetApi(11)
@Override
public Callback getCallback() {
return wrapped.getCallback();
}
@TargetApi(19)
@Override
public int getAlpha() {
return wrapped.getAlpha();
}
@Override
public void setColorFilter(int color, PorterDuff.Mode mode) {
wrapped.setColorFilter(color, mode);
}
@Override
public void clearColorFilter() {
wrapped.clearColorFilter();
}
@Override
public Drawable getCurrent() {
return wrapped.getCurrent();
}
@Override
public boolean setVisible(boolean visible, boolean restart) {
return wrapped.setVisible(visible, restart);
}
@Override
public int getIntrinsicWidth() {
return side;
}
@Override
public int getIntrinsicHeight() {
return side;
}
@Override
public int getMinimumWidth() {
return wrapped.getMinimumWidth();
}
@Override
public int getMinimumHeight() {
return wrapped.getMinimumHeight();
}
@Override
public boolean getPadding(Rect padding) {
return wrapped.getPadding(padding);
}
@Override
public void invalidateSelf() {
super.invalidateSelf(); //To change body of overridden methods use File | Settings | File Templates.
wrapped.invalidateSelf();
}
@Override
public void unscheduleSelf(Runnable what) {
super.unscheduleSelf(what); //To change body of overridden methods use File | Settings | File Templates.
wrapped.unscheduleSelf(what);
}
@Override
public void scheduleSelf(Runnable what, long when) {
super.scheduleSelf(what, when); //To change body of overridden methods use File | Settings | File Templates.
wrapped.scheduleSelf(what, when);
}
@Override
public void draw(Canvas canvas) {
wrapped.draw(canvas);
}
@Override
public void setAlpha(int i) {
wrapped.setAlpha(i);
}
@Override
public void setColorFilter(ColorFilter colorFilter) {
wrapped.setColorFilter(colorFilter);
}
@Override
public int getOpacity() {
return wrapped.getOpacity();
}
}
......@@ -7,7 +7,7 @@ import com.bumptech.glide.request.Request;
/**
* An interface that Glide can load an image into
*
* @param <Z> The type of resource the target can display.
* @param <R> The type of resource the target can display.
*/
public interface Target<R> {
......
<?xml version="1.0" encoding="utf-8"?>
<ImageView xmlns:android="http://schemas.android.com/apk/res/android"
android:scaleType="centerCrop"
android:layout_width="fill_parent"
android:layout_height="fill_parent"/>
......@@ -99,9 +99,8 @@ public class FlickrPhotoGrid extends SherlockFragment implements PhotoViewer {
protected GenericRequestBuilder getRequestBuilder(Photo item) {
return Glide.with(FlickrPhotoGrid.this)
.loadFromImage(item)
.override(Api.THUMB_SIZE, Api.THUMB_SIZE)
.priority(Priority.HIGH)
.centerCrop();
.override(Api.SQUARE_THUMB_SIZE, Api.SQUARE_THUMB_SIZE)
.priority(Priority.HIGH);
}
}
......@@ -150,8 +149,7 @@ public class FlickrPhotoGrid extends SherlockFragment implements PhotoViewer {
.loadFromImage(current)
.thumbnail(Glide.with(FlickrPhotoGrid.this)
.loadFromImage(current)
.override(Api.THUMB_SIZE, Api.THUMB_SIZE)
.centerCrop()
.override(Api.SQUARE_THUMB_SIZE, Api.SQUARE_THUMB_SIZE)
)
.animate(R.anim.fade_in)
.centerCrop()
......
......@@ -115,8 +115,9 @@ public class FlickrPhotoList extends SherlockFragment implements PhotoViewer {
return Glide.with(FlickrPhotoList.this)
.loadFromImage(item)
.thumbnail(Glide.with(FlickrPhotoList.this)
.loadFromImage(item)
.override(Api.THUMB_SIZE, Api.THUMB_SIZE))
.loadFromImage(item)
.override(Api.SQUARE_THUMB_SIZE, Api.SQUARE_THUMB_SIZE)
)
.centerCrop();
}
}
......@@ -176,7 +177,7 @@ public class FlickrPhotoList extends SherlockFragment implements PhotoViewer {
.placeholder(new ColorDrawable(Color.GRAY))
.thumbnail(Glide.with(FlickrPhotoList.this)
.loadFromImage(current)
.override(Api.THUMB_SIZE, Api.THUMB_SIZE))
.override(Api.SQUARE_THUMB_SIZE, Api.SQUARE_THUMB_SIZE))
.centerCrop()
.crossFade(R.anim.fade_in, 150)
.into(viewHolder.imageView);
......
......@@ -45,7 +45,7 @@ public class Api {
Collections.sort(SORTED_SIZE_KEYS);
}
public static final int THUMB_SIZE = SORTED_SIZE_KEYS.get(0);
public static final int SQUARE_THUMB_SIZE = SORTED_SIZE_KEYS.get(0);
private static String getSizeKey(int width, int height) {
final int largestEdge = Math.max(width, height);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册