Universal Image loader有时无法加载图像

Dat*_*shi 10 android universal-image-loader

我正在使用通用图像加载器,我每天都会收到大量无法为用户加载的图像.我正在使用此代码将错误归结为分析.

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);
  }
}
Run Code Online (Sandbox Code Playgroud)

大部分时间它捕获异常,因为getType或getCause为null.在具有2.1-2.3安卓版本的设备上可以看到此问题,但有一些报告来自较新版本,如4.0.4甚至4.2.2.所以我无法确定导致图像无法加载的原因

另一个问题是IO_ERROR java.io.EOFException,主要出现在较新的Android版本上.

第三个最常见的错误是out_of_memory错误...我试图加载的图像不大于1mb,但我需要有ScaleType.Exactly,但是在加载更大的图像时我不会将它们缓存在内存或光盘中,以减少out_of_memory的可能性,但它仍然经常发生.

我的配置:

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();
Run Code Online (Sandbox Code Playgroud)

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

更新 当我更改了nostra建议的代码时onLoadingFailed,我现在看到所有没有的报告.getCause()都是"DECODING_ERROR",所有这些都是由android 2.2-2.3.6版本报告的,没有来自较新的版本.然而我的大部分用户仍然使用较旧的机器人,任何想法如何减少这个decode_error?我自己检查了旧版机器人的应用程序,图像大部分时间都会加载,但DECODING_ERROR最常报告的是分析.其次,最受欢迎的原因仍然是相同的IO_ERROR java.io.EOFException

更新2

定制下载器作为nostra建议,减少threadPoolSize为3设置额外加载 - 如果加载失败尝试再次加载一次然后放弃.我看到加载失败减少了约30%.但仍然会发生 - 500个日常活跃用户在3天内发生100次解码错误(仅限2.2-2.3.6版本)和160次EOF错误(4.0次及以上).

更新3

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

nos*_*a13 5

failReason.getType()不能nullfailReason.getCause()可以.你应该检查它以防止NPE.

failReason.getCause()null如果你通过拒绝网络ImageLoader.denyNetworkDownloads(true)或者如果发生解码错误.这是因为Android无法通过某种原因解码图像.

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

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

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

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;
}
}
Run Code Online (Sandbox Code Playgroud)

或者自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;
    }
}
Run Code Online (Sandbox Code Playgroud)