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

initial working version of preloading

上级 8b2c41e5
package com.bumptech.glide;
import android.annotation.TargetApi;
import android.content.Context;
import android.graphics.Bitmap;
import android.os.Build;
import android.widget.AbsListView;
import com.bumptech.glide.presenter.target.SimpleTarget;
import java.util.ArrayDeque;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;
public abstract class ListPreloader<T> implements AbsListView.OnScrollListener {
private final int maxPreload;
private final Context context;
private final PreloadTargetQueue preloadTargetQueue;
private int lastEnd;
private int lastStart;
private int lastFirstVisible;
private int totalItemCount;
public ListPreloader(Context context, int maxPreload) {
this.context = context;
this.maxPreload = maxPreload;
preloadTargetQueue = new PreloadTargetQueue(maxPreload);
}
@Override
public void onScrollStateChanged(AbsListView absListView, int i) { }
@Override
public void onScroll(AbsListView absListView, int firstVisible, int visibleCount, int totalCount) {
totalItemCount = totalCount;
if (firstVisible > lastFirstVisible) {
preload(firstVisible + visibleCount, true);
} else if (firstVisible < lastFirstVisible) {
preload(firstVisible, false);
}
lastFirstVisible = firstVisible;
}
protected abstract int[] getDimens(T item);
protected abstract List<T> getItems(int start, int end);
protected abstract Glide.Request<T> getRequest(T item);
public void preload(int start, boolean increasing) {
preload(start, start + (increasing ? maxPreload : -maxPreload));
}
private void preload(int from, int to) {
int start;
int end;
if (from < to) {
start = Math.max(lastEnd, from);
end = to;
} else {
start = to;
end = Math.min(lastStart, from);
}
end = Math.min(totalItemCount, end);
start = Math.min(totalItemCount, Math.max(0, start));
List<T> items = getItems(start, end);
// Increasing
if (from < to) {
final int numItems = items.size();
for (int i = 0; i < numItems; i++) {
preload(items, i);
}
} else {
for (int i = items.size() - 1; i >= 0; i--) {
preload(items, i);
}
}
lastStart = start;
lastEnd = end;
}
private void preload(List<T> items, int position) {
final T item = items.get(position);
int[] dimens = getDimens(item);
getRequest(item).into(preloadTargetQueue.next(dimens[0], dimens[1])).with(context);
}
private static class PreloadTargetQueue {
private final Queue<PreloadTarget> queue;
@TargetApi(9)
private PreloadTargetQueue(int size) {
if (Build.VERSION.SDK_INT >= 9) {
queue = new ArrayDeque<PreloadTarget>(size);
} else {
queue = new LinkedList<PreloadTarget>();
}
for (int i = 0; i < size; i++) {
queue.offer(new PreloadTarget());
}
}
public PreloadTarget next(int width, int height) {
final PreloadTarget result = queue.poll();
queue.offer(result);
result.photoWidth = width;
result.photoHeight = height;
return result;
}
}
private static class PreloadTarget extends SimpleTarget {
private int photoHeight;
private int photoWidth;
@Override
protected int[] getSize() {
return new int[] { photoWidth, photoHeight };
}
@Override
public void onImageReady(Bitmap bitmap) { }
}
}
...@@ -16,11 +16,10 @@ import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT; ...@@ -16,11 +16,10 @@ import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
* purposes. * purposes.
*/ */
public class ImageManagerLoader implements ImageLoader { public class ImageManagerLoader implements ImageLoader {
private final ImageManager imageManager;
protected final ImageManager imageManager;
private final Downsampler downsampler; private final Downsampler downsampler;
private Bitmap acquired; private Bitmap acquired;
private ImageManager.ImageManagerJob loadToken; private ImageManager.LoadToken loadToken;
public ImageManagerLoader(Context context) { public ImageManagerLoader(Context context) {
this(context, Downsampler.AT_LEAST); this(context, Downsampler.AT_LEAST);
...@@ -40,13 +39,14 @@ public class ImageManagerLoader implements ImageLoader { ...@@ -40,13 +39,14 @@ public class ImageManagerLoader implements ImageLoader {
} }
@Override @Override
public Object fetchImage(String id, StreamLoader streamLoader, Transformation transformation, int width, int height, final ImageReadyCallback cb) { public Object fetchImage(String id, StreamLoader streamLoader, Transformation transformation, int width, int height,
final ImageReadyCallback cb) {
if (!isHandled(width, height)) { if (!isHandled(width, height)) {
throw new IllegalArgumentException(getClass() + " cannot handle width=" + width + " and/or height =" + throw new IllegalArgumentException(getClass() + " cannot handle width=" + width + " and/or height =" +
height); height);
} }
loadToken = imageManager.getImage(id, streamLoader, transformation, downsampler, width, height, new LoadedCallback() { loadToken = imageManager.getImage(id, streamLoader, transformation, downsampler, width, height,
new LoadedCallback() {
@Override @Override
public void onLoadCompleted(Bitmap loaded) { public void onLoadCompleted(Bitmap loaded) {
onImageReady(loaded, cb.onImageReady(loaded)); onImageReady(loaded, cb.onImageReady(loaded));
......
...@@ -9,10 +9,7 @@ import android.app.ActivityManager; ...@@ -9,10 +9,7 @@ import android.app.ActivityManager;
import android.content.Context; import android.content.Context;
import android.graphics.Bitmap; import android.graphics.Bitmap;
import android.graphics.BitmapFactory; import android.graphics.BitmapFactory;
import android.os.Build; import android.os.*;
import android.os.Environment;
import android.os.Handler;
import android.os.HandlerThread;
import com.bumptech.glide.loader.stream.StreamLoader; import com.bumptech.glide.loader.stream.StreamLoader;
import com.bumptech.glide.resize.bitmap_recycle.BitmapPool; import com.bumptech.glide.resize.bitmap_recycle.BitmapPool;
import com.bumptech.glide.resize.bitmap_recycle.BitmapPoolAdapter; import com.bumptech.glide.resize.bitmap_recycle.BitmapPoolAdapter;
...@@ -35,16 +32,23 @@ import java.io.File; ...@@ -35,16 +32,23 @@ import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.OutputStream; import java.io.OutputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutorService; import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors; import java.util.concurrent.Executors;
import java.util.concurrent.Future; import java.util.concurrent.Future;
import java.util.concurrent.ThreadFactory; import java.util.concurrent.ThreadFactory;
import static android.os.Process.THREAD_PRIORITY_BACKGROUND;
/** /**
* A class to coordinate image loading, resizing, recycling, and caching. Depending on the provided options and the * A class to coordinate image loading, resizing, recycling, and caching. Depending on the provided options and the
* sdk version, uses a combination of an LRU disk cache and an LRU hard memory cache to try to reduce the number of * sdk version, uses a combination of an LRU disk cache and an LRU hard memory cache to try to reduce the number of
* load and resize operations performed and to maximize the number of times Bitmaps are recycled as opposed to * load and resize operations performed and to maximize the number of times Bitmaps are recycled as opposed to
* allocated. If no options are given defaults to using both a memory and a disk cache and to recycling bitmaps if possible. * allocated. If no options are given defaults to using both a memory and a disk cache and to recycling bitmaps if
* possible.
* *
* <p> * <p>
* Note that Bitmap recycling is only available on Honeycomb and up. * Note that Bitmap recycling is only available on Honeycomb and up.
...@@ -60,6 +64,7 @@ public class ImageManager { ...@@ -60,6 +64,7 @@ public class ImageManager {
private final BitmapReferenceCounter bitmapReferenceCounter; private final BitmapReferenceCounter bitmapReferenceCounter;
private final int bitmapCompressQuality; private final int bitmapCompressQuality;
private final BitmapPool bitmapPool; private final BitmapPool bitmapPool;
private final Map<String, ImageManagerJob> jobs = new HashMap<String, ImageManagerJob>();
private boolean shutdown = false; private boolean shutdown = false;
private final Handler mainHandler = new Handler(); private final Handler mainHandler = new Handler();
...@@ -75,7 +80,8 @@ public class ImageManager { ...@@ -75,7 +80,8 @@ public class ImageManager {
private static Downsampler DISK_CACHE_DOWNSAMPLER = new Downsampler() { private static Downsampler DISK_CACHE_DOWNSAMPLER = new Downsampler() {
@Override @Override
public Bitmap downsample(RecyclableBufferedInputStream bis, BitmapFactory.Options options, BitmapPool pool, int outWidth, int outHeight) { public Bitmap downsample(RecyclableBufferedInputStream bis, BitmapFactory.Options options, BitmapPool pool,
int outWidth, int outHeight) {
return downsampleWithSize(bis, options, pool, outWidth, outHeight, 1); return downsampleWithSize(bis, options, pool, outWidth, outHeight, 1);
} }
...@@ -313,11 +319,12 @@ public class ImageManager { ...@@ -313,11 +319,12 @@ public class ImageManager {
private void setDefaults() { private void setDefaults() {
if (resizeService == null) { if (resizeService == null) {
resizeService = Executors.newFixedThreadPool(Math.max(1, Runtime.getRuntime().availableProcessors()), new ThreadFactory() { final int numThreads = Math.max(1, Runtime.getRuntime().availableProcessors());
resizeService = Executors.newFixedThreadPool(numThreads, new ThreadFactory() {
@Override @Override
public Thread newThread(Runnable runnable) { public Thread newThread(Runnable runnable) {
final Thread result = new Thread(runnable); final Thread result = new Thread(runnable);
result.setPriority(Thread.MIN_PRIORITY); result.setPriority(THREAD_PRIORITY_BACKGROUND);
return result; return result;
} }
}); });
...@@ -356,7 +363,7 @@ public class ImageManager { ...@@ -356,7 +363,7 @@ public class ImageManager {
} }
private ImageManager(Builder builder) { private ImageManager(Builder builder) {
HandlerThread bgThread = new HandlerThread("bg_thread", android.os.Process.THREAD_PRIORITY_BACKGROUND); HandlerThread bgThread = new HandlerThread("bg_thread", THREAD_PRIORITY_BACKGROUND);
bgThread.start(); bgThread.start();
bgHandler = new Handler(bgThread.getLooper()); bgHandler = new Handler(bgThread.getLooper());
executor = builder.resizeService; executor = builder.resizeService;
...@@ -366,7 +373,6 @@ public class ImageManager { ...@@ -366,7 +373,6 @@ public class ImageManager {
bitmapReferenceCounter = builder.bitmapReferenceCounter; bitmapReferenceCounter = builder.bitmapReferenceCounter;
bitmapPool = builder.bitmapPool; bitmapPool = builder.bitmapPool;
resizer = new ImageResizer(builder.bitmapPool, builder.decodeBitmapOptions); resizer = new ImageResizer(builder.bitmapPool, builder.decodeBitmapOptions);
memoryCache.setImageRemovedListener(new MemoryCache.ImageRemovedListener() { memoryCache.setImageRemovedListener(new MemoryCache.ImageRemovedListener() {
@Override @Override
public void onImageRemoved(Bitmap removed) { public void onImageRemoved(Bitmap removed) {
...@@ -404,18 +410,25 @@ public class ImageManager { ...@@ -404,18 +410,25 @@ public class ImageManager {
* @return An {@link ImageManagerJob} that must be retained while the job is still relevant and that can be used * @return An {@link ImageManagerJob} that must be retained while the job is still relevant and that can be used
* to cancel a job if the image is no longer needed * to cancel a job if the image is no longer needed
*/ */
public ImageManagerJob getImage(String id, StreamLoader streamLoader, Transformation transformation, Downsampler downsampler, int width, int height, LoadedCallback cb) { public LoadToken getImage(String id, StreamLoader streamLoader, Transformation transformation,
Downsampler downsampler, int width, int height, LoadedCallback cb) {
if (shutdown) return null; if (shutdown) return null;
final String key = safeKeyGenerator.getSafeKey(id, transformation, downsampler, width, height); final String key = safeKeyGenerator.getSafeKey(id, transformation, downsampler, width, height);
LoadToken result = null;
ImageManagerJob job = null;
if (!returnFromCache(key, cb)) { if (!returnFromCache(key, cb)) {
ImageManagerRunner runner = new ImageManagerRunner(key, streamLoader, transformation, downsampler, width, height, cb); ImageManagerJob job = jobs.get(key);
runner.execute(); if (job == null) {
job = new ImageManagerJob(runner, streamLoader, transformation, downsampler, cb); ImageManagerRunner runner = new ImageManagerRunner(key, streamLoader, transformation, downsampler,
width, height);
job = new ImageManagerJob(runner, key);
jobs.put(key, job);
runner.execute();
}
job.addCallback(cb);
result = new LoadToken(cb, job);
} }
return job; return result;
} }
/** /**
...@@ -464,30 +477,69 @@ public class ImageManager { ...@@ -464,30 +477,69 @@ public class ImageManager {
* A class for tracking a particular job in the {@link ImageManager}. Cancel does not guarantee that the * A class for tracking a particular job in the {@link ImageManager}. Cancel does not guarantee that the
* job will not finish, but rather is a best effort attempt. * job will not finish, but rather is a best effort attempt.
*/ */
public static class ImageManagerJob { private class ImageManagerJob {
private final ImageManagerRunner runner; private final ImageManagerRunner runner;
private StreamLoader sl; private final String key;
private Transformation transformation; private final List<LoadedCallback> cbs = new ArrayList<LoadedCallback>();
private Downsampler downsampler;
private LoadedCallback cb;
public ImageManagerJob(ImageManagerRunner runner, StreamLoader sl, Transformation t, Downsampler d, LoadedCallback cb) { public ImageManagerJob(ImageManagerRunner runner, String key) {
this.runner = runner; this.runner = runner;
this.sl = sl; this.key = key;
this.transformation = t; }
this.downsampler = d;
this.cb = cb; public void addCallback(LoadedCallback cb) {
cbs.add(cb);
} }
/** /**
* Try to cancel the job. Does not guarantee that the job will not finish. * Try to cancel the job. Does not guarantee that the job will not finish.
*/ */
public void cancel() { public void cancel(LoadedCallback cb) {
runner.cancel(); cbs.remove(cb);
sl = null; if (cbs.size() == 0) {
transformation = null; runner.cancel();
downsampler = null; jobs.remove(key);
cb = null; }
}
public void onLoadComplete(Bitmap result) {
for (LoadedCallback cb : cbs) {
bitmapReferenceCounter.acquireBitmap(result);
cb.onLoadCompleted(result);
}
jobs.remove(key);
}
public void onLoadFailed(Exception e) {
for (LoadedCallback cb : cbs) {
cb.onLoadFailed(e);
}
jobs.remove(key);
}
}
private void putInDiskCache(String key, final Bitmap bitmap) {
diskCache.put(key, new DiskCache.Writer() {
@Override
public void write(OutputStream os) {
final Bitmap.Config config = bitmap.getConfig();
final Bitmap.CompressFormat format;
if (config == null || config == Bitmap.Config.ARGB_4444 || config == Bitmap.Config.ARGB_8888) {
format = Bitmap.CompressFormat.PNG;
} else {
format = Bitmap.CompressFormat.JPEG;
}
bitmap.compress(format, bitmapCompressQuality, os);
}
});
}
private void putInMemoryCache(String key, final Bitmap bitmap) {
final boolean inCache;
inCache = memoryCache.contains(key);
if (!inCache) {
bitmapReferenceCounter.acquireBitmap(bitmap);
memoryCache.put(key, bitmap);
} }
} }
...@@ -498,12 +550,11 @@ public class ImageManager { ...@@ -498,12 +550,11 @@ public class ImageManager {
private final StreamLoader streamLoader; private final StreamLoader streamLoader;
private final Transformation transformation; private final Transformation transformation;
private final Downsampler downsampler; private final Downsampler downsampler;
private final LoadedCallback cb;
private volatile Future<?> future; private volatile Future<?> future;
private volatile boolean cancelled = false; private volatile boolean cancelled = false;
public ImageManagerRunner(String key, StreamLoader sl, Transformation t, Downsampler d, int width, int height, LoadedCallback cb) { public ImageManagerRunner(String key, StreamLoader sl, Transformation t, Downsampler d, int width, int height) {
this.key = key; this.key = key;
this.height = height; this.height = height;
this.width = width; this.width = width;
...@@ -511,7 +562,6 @@ public class ImageManager { ...@@ -511,7 +562,6 @@ public class ImageManager {
this.streamLoader = sl; this.streamLoader = sl;
this.transformation = t; this.transformation = t;
this.downsampler = d; this.downsampler = d;
this.cb = cb;
} }
private void execute() { private void execute() {
...@@ -618,9 +668,11 @@ public class ImageManager { ...@@ -618,9 +668,11 @@ public class ImageManager {
//acquire for the callback before putting in to memory cache so that the bitmap is not //acquire for the callback before putting in to memory cache so that the bitmap is not
//released to the pool if the bitmap is synchronously released by the memory cache //released to the pool if the bitmap is synchronously released by the memory cache
//we rely on the callback to call releaseBitmap if it doesn't want to use the bitmap //we rely on the callback to call releaseBitmap if it doesn't want to use the bitmap
bitmapReferenceCounter.acquireBitmap(result);
putInMemoryCache(key, result); putInMemoryCache(key, result);
cb.onLoadCompleted(result); final ImageManagerJob job = jobs.get(key);
if (job != null) {
job.onLoadComplete(result);
}
} }
}); });
} else { } else {
...@@ -632,34 +684,26 @@ public class ImageManager { ...@@ -632,34 +684,26 @@ public class ImageManager {
mainHandler.post(new Runnable() { mainHandler.post(new Runnable() {
@Override @Override
public void run() { public void run() {
cb.onLoadFailed(e); final ImageManagerJob job = jobs.get(key);
if (job != null) {
job.onLoadFailed(e);
}
} }
}); });
} }
} }
private void putInDiskCache(String key, final Bitmap bitmap) { public static class LoadToken {
diskCache.put(key, new DiskCache.Writer() { private final ImageManagerJob job;
@Override private final LoadedCallback cb;
public void write(OutputStream os) {
final Bitmap.Config config = bitmap.getConfig();
final Bitmap.CompressFormat format;
if (config == null || config == Bitmap.Config.ARGB_4444 || config == Bitmap.Config.ARGB_8888) {
format = Bitmap.CompressFormat.PNG;
} else {
format = Bitmap.CompressFormat.JPEG;
}
bitmap.compress(format, bitmapCompressQuality, os);
}
});
}
private void putInMemoryCache(String key, final Bitmap bitmap) { public LoadToken(LoadedCallback cb, ImageManagerJob job) {
final boolean inCache; this.cb = cb;
inCache = memoryCache.contains(key); this.job = job;
if (!inCache) { }
bitmapReferenceCounter.acquireBitmap(bitmap);
memoryCache.put(key, bitmap); public void cancel() {
job.cancel(cb);
} }
} }
} }
...@@ -11,6 +11,8 @@ import android.widget.BaseAdapter; ...@@ -11,6 +11,8 @@ import android.widget.BaseAdapter;
import android.widget.GridView; import android.widget.GridView;
import android.widget.ImageView; import android.widget.ImageView;
import com.actionbarsherlock.app.SherlockFragment; import com.actionbarsherlock.app.SherlockFragment;
import com.bumptech.glide.Glide;
import com.bumptech.glide.ListPreloader;
import com.bumptech.glide.loader.image.ImageManagerLoader; import com.bumptech.glide.loader.image.ImageManagerLoader;
import com.bumptech.glide.loader.model.Cache; import com.bumptech.glide.loader.model.Cache;
import com.bumptech.glide.loader.transformation.CenterCrop; import com.bumptech.glide.loader.transformation.CenterCrop;
...@@ -22,15 +24,9 @@ import java.net.URL; ...@@ -22,15 +24,9 @@ import java.net.URL;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
/**
* Created with IntelliJ IDEA.
* User: sam
* Date: 1/10/13
* Time: 9:48 AM
* To change this template use File | Settings | File Templates.
*/
public class FlickrPhotoGrid extends SherlockFragment implements PhotoViewer { public class FlickrPhotoGrid extends SherlockFragment implements PhotoViewer {
private static final String IMAGE_SIZE_KEY = "image_size"; private static final String IMAGE_SIZE_KEY = "image_size";
private static final int PRELOAD_COUNT = 10;
private PhotoAdapter adapter; private PhotoAdapter adapter;
private List<Photo> currentPhotos; private List<Photo> currentPhotos;
...@@ -51,8 +47,10 @@ public class FlickrPhotoGrid extends SherlockFragment implements PhotoViewer { ...@@ -51,8 +47,10 @@ public class FlickrPhotoGrid extends SherlockFragment implements PhotoViewer {
photoSize = args.getInt(IMAGE_SIZE_KEY); photoSize = args.getInt(IMAGE_SIZE_KEY);
final View result = inflater.inflate(R.layout.flickr_photo_grid, container, false); final View result = inflater.inflate(R.layout.flickr_photo_grid, container, false);
GridView grid = (GridView) result.findViewById(R.id.images); final GridView grid = (GridView) result.findViewById(R.id.images);
grid.setColumnWidth(photoSize); grid.setColumnWidth(photoSize);
final FlickrPreloader preloader = new FlickrPreloader(getActivity(), PRELOAD_COUNT);
grid.setOnScrollListener(preloader);
adapter = new PhotoAdapter(); adapter = new PhotoAdapter();
grid.setAdapter(adapter); grid.setAdapter(adapter);
if (currentPhotos != null) if (currentPhotos != null)
...@@ -68,8 +66,30 @@ public class FlickrPhotoGrid extends SherlockFragment implements PhotoViewer { ...@@ -68,8 +66,30 @@ public class FlickrPhotoGrid extends SherlockFragment implements PhotoViewer {
adapter.setPhotos(currentPhotos); adapter.setPhotos(currentPhotos);
} }
private class PhotoAdapter extends BaseAdapter { private class FlickrPreloader extends ListPreloader<Photo> {
public FlickrPreloader(Context context, int toPreload) {
super(context, toPreload);
}
@Override
protected int[] getDimens(Photo item) {
return new int[] { photoSize, photoSize };
}
@Override
protected List<Photo> getItems(int start, int end) {
return currentPhotos.subList(start, end);
}
@Override
protected Glide.Request<Photo> getRequest(Photo item) {
return Glide.using(new FlickrModelLoader(getActivity(), urlCache))
.load(item)
.centerCrop();
}
}
private class PhotoAdapter extends BaseAdapter {
private List<Photo> photos = new ArrayList<Photo>(0); private List<Photo> photos = new ArrayList<Photo>(0);
private final LayoutInflater inflater; private final LayoutInflater inflater;
...@@ -135,6 +155,6 @@ public class FlickrPhotoGrid extends SherlockFragment implements PhotoViewer { ...@@ -135,6 +155,6 @@ public class FlickrPhotoGrid extends SherlockFragment implements PhotoViewer {
imagePresenter.setModel(current); imagePresenter.setModel(current);
return view; return view;
} }
}
}
} }
...@@ -21,6 +21,7 @@ import com.bumptech.glide.resize.ImageManager; ...@@ -21,6 +21,7 @@ import com.bumptech.glide.resize.ImageManager;
import com.bumptech.glide.resize.cache.DiskCache; import com.bumptech.glide.resize.cache.DiskCache;
import com.bumptech.glide.resize.cache.DiskCacheAdapter; import com.bumptech.glide.resize.cache.DiskCacheAdapter;
import com.bumptech.glide.resize.cache.DiskLruCacheWrapper; import com.bumptech.glide.resize.cache.DiskLruCacheWrapper;
import com.bumptech.glide.resize.cache.LruMemoryCache;
import com.bumptech.glide.samples.flickr.api.Api; import com.bumptech.glide.samples.flickr.api.Api;
import com.bumptech.glide.samples.flickr.api.Photo; import com.bumptech.glide.samples.flickr.api.Photo;
import com.bumptech.glide.util.Log; import com.bumptech.glide.util.Log;
...@@ -94,6 +95,7 @@ public class FlickrSearchActivity extends SherlockFragmentActivity { ...@@ -94,6 +95,7 @@ public class FlickrSearchActivity extends SherlockFragmentActivity {
glide.setImageManager(new ImageManager.Builder(this) glide.setImageManager(new ImageManager.Builder(this)
.setBitmapCompressQuality(70) .setBitmapCompressQuality(70)
.setMemoryCache(new LruMemoryCache(ImageManager.getSafeMemoryCacheSize(this)/4))
.setDiskCache(diskCache)); .setDiskCache(diskCache));
} }
......
...@@ -90,7 +90,7 @@ public class Api { ...@@ -90,7 +90,7 @@ public class Api {
} }
private static String getSearchUrl(String text) { private static String getSearchUrl(String text) {
return getUrlForMethod("flickr.photos.search") + "&text=" + text + "&per_page=500"; return getUrlForMethod("flickr.photos.search") + "&text=" + text + "&per_page=300";
} }
private static String getPhotoUrl(Photo photo, String sizeKey) { private static String getPhotoUrl(Photo photo, String sizeKey) {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册