我正在使用这个很棒的lib Universal Image Loader
问题: 当我从imge 0反复滚动到240时,我终于达到OutOfMemory异常,然后有一个位图停止加载的时刻(这发生在Galaxy tab 2 Android 4.2.2上)。
在nexus 7上尝试保存全尺寸图像时会出现异常:
java.io.FileNotFoundException: /storage/emulated/0/Android/data/com.bla.bla/cache/Folder/Full/400120282.tmp: open failed: EBUSY (Device or resource busy)
at libcore.io.IoBridge.open(IoBridge.java:409)
at java.io.FileOutputStream.<init>(FileOutputStream.java:88)
at java.io.FileOutputStream.<init>(FileOutputStream.java:73)
at com.nostra13.universalimageloader.cache.disc.impl.BaseDiscCache.save(BaseDiscCache.java:107)
at com.package.workspace.uil.RememberingDiskCache.save(RememberingDiskCache.java:42)
at com.nostra13.universalimageloader.core.LoadAndDisplayImageTask.downloadImage(LoadAndDisplayImageTask.java:291)
at com.nostra13.universalimageloader.core.LoadAndDisplayImageTask.tryCacheImageOnDisk(LoadAndDisplayImageTask.java:273)
at com.nostra13.universalimageloader.core.LoadAndDisplayImageTask.tryLoadBitmap(LoadAndDisplayImageTask.java:229)
at com.nostra13.universalimageloader.core.LoadAndDisplayImageTask.run(LoadAndDisplayImageTask.java:135)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
at java.lang.Thread.run(Thread.java:841)
Lib version 1.9.2,来自克隆源。
Android
<uses-sdk
android:minSdkVersion="16"
android:targetSdkVersion="17" />
所以我使用EcoGallery的图片加载器。 EcoGallery类似于Android Gallery,我有大约280张图片(最多)。
对于每个视图,我有2个网址: 一个缩略图约300 * 200 一个全尺寸约1920 * 2500(取决于但基本上是巨大的)
在ecoGallery中,可以同时显示1到3张图像。
规则基本上是: 显示默认的drawable 下载缩略图 显示缩略图 在此期间下载完整尺寸的img 显示完整尺寸。
使用3和完整大小为1(优先级较低)的线程池下载缩略图
为了下载拇指和完整图像,我有2个imageLoaders。
我的适配器的getView方法调用以下方法:
@Override
public void setUpImageForDownloadableImageView(final ThumbAndFullUrls urls, final ImageView imageView1) {
if(((RememberingDiskCache) imageLoaderFull.getDiskCache()).contains(urls.imageFullUrlAsString) ){
loadFullImage(urls.imageFullUrlAsString, imageView1, null);
} else {
loadThumbImage(urls.imageThumbUrlAsString, imageView1);
}
}
以下是代码的其余部分:
ImageLoader imageLoaderThumb = ImageLoader.getInstance();
File cacheDir1 = new File(StorageUtils.getCacheDirectory(context), ALL_FOLDER_UIL);
UnlimitedDiscCache diskCache = new UnlimitedDiscCache(cacheDir1);
ImageLoaderConfiguration aDefault1 = new ImageLoaderConfiguration.Builder(context.getApplicationContext())
.tasksProcessingOrder(QueueProcessingType.LIFO)
.imageDownloader(new MyImageDownloader(context.getApplicationContext(), socketFactory))
.threadPriority(Thread.NORM_PRIORITY - 2)
.denyCacheImageMultipleSizesInMemory()
.threadPoolSize(1) // default
.diskCache(diskCache)
.memoryCache(lruLimitedMemoryCache)
.diskCacheFileNameGenerator(new HashCodeFileNameGenerator())
.writeDebugLogs()
.build();
imageLoaderThumb.init(aDefault1);
MyImageLoader imageLoaderFull = MyImageLoader.getInstance();
File cacheDir = new File(StorageUtils.getCacheDirectory(applicationContext), IMAGES_FOLDER_UIL);
RememberingDiskCache rememberingDiskCache = new RememberingDiskCache(cacheDir); // remembering
ImageLoaderConfiguration aDefault = new ImageLoaderConfiguration.Builder(context.getApplicationContext())
.tasksProcessingOrder(QueueProcessingType.LIFO)
.imageDownloader(new MyImageDownloader(context.getApplicationContext(), socketFactory))
.threadPriority(Thread.NORM_PRIORITY - 1) // default
.denyCacheImageMultipleSizesInMemory()
.threadPoolSize(1) // default
.diskCache(rememberingDiskCache)
.memoryCache(lruLimitedMemoryCache)// full doesn't use memory cache
.diskCacheFileNameGenerator(new HashCodeFileNameGenerator())//default
.writeDebugLogs()
.build();
imageLoaderFull.init(aDefault);
protected void loadThumbImage(final ThumbAndFullUrls url, final DownloadableImageView imageView1) {
DisplayImageOptions thumbDisplayOptions = new DisplayImageOptions.Builder()
.showImageOnLoading(defaultDrawableToShow)
.showImageForEmptyUri(defaultDrawableToShow)
.showImageOnFail(defaultDrawableToShow)
.cacheInMemory(true)
.cacheOnDisk(true)
.imageScaleType(ImageScaleType.NONE)
.considerExifParams(true) //fixes the weird orientation problem
.bitmapConfig(Bitmap.Config.RGB_565)
.build();
imageLoaderThumb.displayImage(uri.thumbUrl,
imageView1,
thumbDisplayOptions,
new ImageLoadingListener() {
@Override public void onLoadingStarted(String imageUri, View view) {
}
@Override public void onLoadingFailed(String imageUri, View view, FailReason failReason) {
}
@Override public void onLoadingComplete(String imageUri, View view, Bitmap loadedImage) {
//FULL size
loadFullImage(url.fullSizeImageUrl, imageView1, imageView1.getDrawable());
}
@Override public void onLoadingCancelled(String imageUri, View view) {
}
});
}
protected void loadFullImage(String fullSizeImageUrl, DownloadableImageView imageView1, Drawable drawable) {
DisplayImageOptions disaplayOptionsForFull = new DisplayImageOptions.Builder()
.showImageOnLoading(drawable)
.resetViewBeforeLoading(false)
.showImageForEmptyUri(drawable)
.showImageOnFail(drawable)
.imageScaleType(ImageScaleType.EXACTLY)
.cacheInMemory(false)
.cacheOnDisk(true)
.considerExifParams(true)
.bitmapConfig(Bitmap.Config.RGB_565)
.build();
imageLoaderFull.displayImage(fullSizeImageUrl, imageView1, disaplayOptionsForFull,
new ImageLoadingListener() {
@Override public void onLoadingStarted(String imageUri, View view) {
}
@Override public void onLoadingFailed(String imageUri, View view, FailReason failReason) {
}
@Override public void onLoadingComplete(String imageUri, View view, Bitmap loadedImage) {
}
@Override public void onLoadingCancelled(String imageUri, View view) {
}
});
}
public class RememberingDiskCache extends UnlimitedDiscCache {
/**
* Remembers which uris were saved to files for quick access
*
* TODO: this will ignore the files that were saved in another session and doesn't actually check in the file system
* TODO: if user deleted the files or cleared cache, we will not find out
*/
private final ArrayList<String> filesInCache = new ArrayList<String>();
public RememberingDiskCache(File cacheDir) {
super(cacheDir);
}
public RememberingDiskCache(File cacheDir, File reserveCacheDir) {
super(cacheDir, reserveCacheDir);
}
public RememberingDiskCache(File cacheDir, File reserveCacheDir, FileNameGenerator fileNameGenerator) {
super(cacheDir, reserveCacheDir, fileNameGenerator);
}
@Override public boolean save(String imageUri, InputStream imageStream, IoUtils.CopyListener listener) throws IOException {
boolean save = super.save(imageUri, imageStream, listener);
if(save){
addToArray(imageUri);
}
return save;
}
protected void addToArray(String imageUri) {
if(!filesInCache.contains(imageUri)){
filesInCache.add(imageUri);
}
}
@Override public boolean save(String imageUri, Bitmap bitmap) throws IOException {
boolean save = super.save(imageUri, bitmap);
if(save){
addToArray(imageUri);
}
return save;
}
@Override public boolean remove(String imageUri) {
boolean remove = super.remove(imageUri);
if(remove){
filesInCache.remove(imageUri);
}
return remove;
}
@Override public void clear() {
super.clear();
filesInCache.clear();
}
public boolean contains(String imageUri){
return filesInCache.contains(imageUri);
}
public class MyImageLoader extends ImageLoader {
private volatile static MyImageLoader instance;
/** Returns singleton class instance */
public static MyImageLoader getInstance() {
if (instance == null) {
synchronized (ImageLoader.class) {
if (instance == null) {
instance = new MyImageLoader();
}
}
}
return instance;
}
}
public class MyImageDownloader extends BaseImageDownloader {
private final SSLSocketFactory sslSocketFactory;
public MyImageDownloader(Context context, SSLSocketFactory sslSocketFactory) {
super(context);
this.sslSocketFactory = sslSocketFactory;
}
@Override public InputStream getStream(String imageUri, Object extra) throws IOException {
switch (Scheme.ofUri(imageUri)) {
case HTTPS:
return getStreamFromNetwork(imageUri, sslSocketFactory);
default:
return super.getStream(imageUri, extra);
}
}
protected InputStream getStreamFromNetwork(String imageUri, SSLSocketFactory factory) throws IOException {
HttpsURLConnection conn = createConnection(imageUri, factory);
int redirectCount = 0;
while (conn.getResponseCode() / 100 == 3 && redirectCount < MAX_REDIRECT_COUNT) {
conn = createConnection(conn.getHeaderField("Location"), factory);
redirectCount++;
}
InputStream imageStream;
try {
imageStream = conn.getInputStream();
} catch (IOException e) {
// Read all data to allow reuse connection (http://bit.ly/1ad35PY)
IoUtils.readAndCloseStream(conn.getErrorStream());
throw e;
}
return new ContentLengthInputStream(new BufferedInputStream(imageStream, BUFFER_SIZE), conn.getContentLength());
}
protected HttpsURLConnection createConnection(String url, SSLSocketFactory socketFactory) throws IOException {
String encodedUrl = Uri.encode(url, ALLOWED_URI_CHARS);
URL url1 = new URL(encodedUrl);
URLConnection urlConnection = url1.openConnection();
HttpsURLConnection conn = (HttpsURLConnection) urlConnection;
if(socketFactory!=null){
conn.setSSLSocketFactory(socketFactory);
}
conn.setHostnameVerifier(new MyHostNameVerifier(new ThreadChecker()));
conn.setConnectTimeout(connectTimeout);
conn.setReadTimeout(readTimeout);
return conn;
}
}
}
有什么建议吗? 我想知道是否可以同时使用2个装载机,是吗?