通用图像加载器有时无法加载图像 [英] Universal Image loader fails to load images sometimes

查看:79
本文介绍了通用图像加载器有时无法加载图像的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用通用图像加载器,但每天有大量图像无法为用户加载.我正在使用此代码将错误信​​息分析.

I'm using universal image loader and I get quite large numbers of images failing to load for users every day. I'm using this code to get my errors to analytics.

public void onLoadingFailed(String imageUri, View view, FailReason failReason) {
  try
  {
    String fail = failReason.getType().toString();
    String fail4 = failReason.getCause().toString();
    String sum = fail + " " + fail4;
    EasyTracker.getTracker().sendException(sum, false);
  }
  catch (Exception e)
  {
    EasyTracker.getTracker().sendException(e.getMessage(), false);
  }
}

在大多数情况下,它会捕获异常,因为getType或getCause为null.在具有2.1-2.3 android版本的设备上可以看到此问题,但是有一些来自较新版本的报告,例如4.0.4甚至4.2.2.所以我真的无法分辨是什么原因导致图像无法加载

Most of the time it catches exception, as getType, or getCause is null. This issue is seen on devices with 2.1-2.3 android versions, but there are some reports from newer version like 4.0.4 or even 4.2.2. So I can't really tell what caused the image failing to load

另一个问题是 IO_ERROR java.io.EOFException ,该问题通常出现在较新的android版本中.

Another issue is IO_ERROR java.io.EOFException, which is mostly seen on newer android versions.

第三种最常见的错误是out_of_memory错误...我要加载的图像不大于1mb,但是我需要具有ScaleType.确切地,但是在加载较大的图像时,我没有将它们缓存在内存或光盘中,以减少out_of_memory的可能性,但是它仍然确实经常发生.

Third of most common errors are out_of_memory errors... The images I am trying to load are no bigger than 1mb, but I need to have ScaleType.Exactly, but while loading larger images I am not caching them in memory or disc, to reduce possibility of out_of_memory, but it still does occur pretty often.

我的配置:

ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(xxx.getApplicationContext())
.threadPoolSize(4)
.memoryCache(new WeakMemoryCache())
.imageDownloader(new BaseImageDownloader(xxx.getApplicationContext(),10 * 1000, 30 * 1000)) 
.build();

if(!ImageLoader.getInstance().isInited())
            ImageLoader.getInstance().init(config);

// options is used for images smaller in size (5kb-150kb)
options = new DisplayImageOptions.Builder()
.cacheInMemory()
.cacheOnDisc()
.showStubImage(R.drawable.stub)
.showImageOnFail(R.drawable.failed)
.imageScaleType(ImageScaleType.EXACTLY)
.bitmapConfig(Bitmap.Config.RGB_565)
.build();

// options2 is used for images big in size (300kb-1,2mb)
options2 = new DisplayImageOptions.Builder()
.showStubImage(R.drawable.stub)
.showImageOnFail(R.drawable.failed)
.imageScaleType(ImageScaleType.NONE) // NONE because I need to have full size bitmap loaded
.bitmapConfig(Bitmap.Config.RGB_565)
.build();

谁能告诉我如何优化我的imageLoading以减少加载失败的次数?因为我感觉由于这些不断加载图像的失败,我失去了一些用户.

Could anyone tell me how could I optimize my imageLoading to get less failed to load images? Because I feel like I am loosing users some because of these constant failings to load images.

更新当我按照nocode在 onLoadingFailed 上建议的代码进行更改时,我现在看到所有不具有 .getCause()的报告都是"DECODING_ERROR",而所有这些都是由android 2.2-2.3.6版本报告,没有来自较新版本的报告.但是我的用户中仍然有很大一部分是在较旧的android上,有什么主意如何减少此解码错误?我在较旧的Android设备上亲自检查了应用程序,并且大多数时候确实加载了图像,但是在分析中报告 DECODING_ERROR 的频率最高.其次,最流行的原因仍然是相同的 IO_ERROR java.io.EOFException

Update As I changed the code as nostra suggested on onLoadingFailed, I'm now seeing that all the reports which does not have .getCause() are "DECODING_ERROR" and all these are reported by android 2.2-2.3.6 versions, none from newer ones. Yet still large portion of my users are on older androids, any idea how to reduce this decoding_error? I checked app myself on older androids, and images do load most of the time, but DECODING_ERROR is reported most often on analytics. Second on most popular reasons is still the same IO_ERROR java.io.EOFException

更新2

如nostra建议的自定义下载程序,将threadPoolSize减小为3设置了额外的加载-如果加载失败,请尝试再次加载一次,然后放弃.我看到加载失败的次数减少了约30%.但仍然会发生-从500个每日活跃用户开始的3天中,出现100个解码错误(仅在2.2-2.3.6版本上唯一),以及160个EOF错误(4.0及更高版本).

Customized Downloader as nostra suggested, reduced threadPoolSize to 3 set up an extra loading - if loading failed try to load again for one time before giving up. I see failings to load decreased about 30%. But still do occur - 100 decoding errors (exclusively only on 2.2-2.3.6 versions) , and 160 EOF errors (4.0 and up) in 3 days from 500 daily active users.

更新3

最新的更新版本获得的解码错误和EOFExceptions更少,我认为主要是因为如果第一次加载失败,我会尝试重新加载同一张图像.但是..我现在面临另一个问题:设备 java.io.IOException上没有剩余空间:写入失败:ENOSPC(设备上没有剩余空间).我正在使用LimitedDiscCache.

Latest updated version gets far less decoding errors and EOFExceptions, I think mainly because I try to reload the same image if it fails to load the first time. But.. I am now face another issue: No space left on device java.io.IOException: write failed: ENOSPC (No space left on device). I am using LimitedDiscCache.

推荐答案

failReason.getType()不能为 null ,但 failReason.getCause()可以.您应该检查它以防止NPE.

failReason.getType() can't be null but failReason.getCause() can. You should check it to prevent NPE.

failReason.getCause()可以为 null .这是因为Android由于某种原因无法解码图像.

failReason.getCause() can be null if you deny network by ImageLoader.denyNetworkDownloads(true) or if decoding error occurred. This is because Android can't decode image by some reason.

顺便说一句,我建议您即使对于大图像( options2 )也要使用 .cacheOnDisc().也许尝试其他内存缓存实现?例如. LruMemoryCache .

BTW I recommend you to use .cacheOnDisc() even for big images (options2). And maybe try other memory cache implementation? E.g. LruMemoryCache.

我不知道 java.io.EOFException 的原因,但是您可以检测到那时使用的是哪个网络吗?手机还是WiFi?也许尝试使用 ImageLoader.handleSlowNetwork(boolean)在网络类型之间进行切换.

I don't know the reason of java.io.EOFException but can you detect which network is used in that time? Mobile or WiFi? Maybe try use ImageLoader.handleSlowNetwork(boolean) to switch between network types.

UPD::也请尝试减小线程池的大小.也许有助于防止解码错误. UPD2::网站重定向到网页可能会导致解码错误.您可以尝试扩展 BaseImageDownloader 并在请求中为"User-Agent"标头添加空字符串.

UPD: Also try to reduce thread pool size. Maybe it helps to prevent DECODING ERRORS. UPD2: Decoding error can be caused by web site redirect to web page. You can try extend BaseImageDownloader and add empty string for "User-Agent" header in request.

public class MyImageDownloader extends BaseImageDownloader {

private static final int MAX_REDIRECT_COUNT = 5;

public MyImageDownloader(Context context) {
    super(context);
}

protected InputStream getStreamFromNetwork(String imageUri, Object extra) throws IOException {
    HttpURLConnection conn = connectTo(imageUri);

    int redirectCount = 0;
    while (conn.getResponseCode() / 100 == 3 && redirectCount < MAX_REDIRECT_COUNT) {
        conn = connectTo(conn.getHeaderField("Location"));
        redirectCount++;
    }

    return new BufferedInputStream(conn.getInputStream(), BUFFER_SIZE);
}

protected HttpURLConnection connectTo(String url) throws IOException {
    String encodedUrl = Uri.encode(url, ALLOWED_URI_CHARS);
    HttpURLConnection conn = (HttpURLConnection) new URL(encodedUrl).openConnection();
    conn.setConnectTimeout(connectTimeout);
    conn.setReadTimeout(readTimeout);
    conn.setRequestProperty("User-Agent", "");
    return conn;
}
}

或者从UIL 1.8.5开始:

Or since UIL 1.8.5:

public class MyImageDownloader extends BaseImageDownloader {
    @Override
    protected HttpURLConnection createConnection(String url) throws IOException {
        HttpURLConnection conn = super.createConnection(url);
        conn.setRequestProperty("User-Agent", "");
        return conn;
    }
}

这篇关于通用图像加载器有时无法加载图像的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆