10

我正在使用通用图像加载器,并且每天都有大量图像无法为用户加载。我正在使用此代码将我的错误用于分析。

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 为空。这个问题出现在 2.1-2.3 android 版本的设备上,但有一些来自较新版本的报告,如 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();

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

更新 当我按照 nostra 的建议更改代码时onLoadingFailed,我现在看到所有没有的报告.getCause()都是“DECODING_ERROR”,所有这些都是由 android 2.2-2.3.6 版本报告的,没有来自较新版本的报告。然而,我的大部分用户仍然使用较旧的机器人,知道如何减少这种解码错误吗?我自己在较旧的 android 上检查了应用程序,并且大多数时间都会加载图像,但DECODING_ERROR最常在分析中报告。第二个最受欢迎的原因仍然相同IO_ERROR java.io.EOFException

更新 2

按照 nostra 的建议定制下载器,将 threadPoolSize 减少到 3 设置额外的加载 - 如果加载失败,请在放弃之前尝试再次加载一次。我看到加载失败减少了大约 30%。但仍然会发生 - 100 个解码错误(仅在 2.2-2.3.6 版本上)和 3 天内来自 500 个每日活跃用户的 160 个 EOF 错误(4.0 及更高版本)。

更新 3

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

4

2 回答 2

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;
}
}

或者从 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;
    }
}
于 2013-05-20T20:27:02.093 回答
4

我从未使用过 Universal Image Loader,但在过去的几周里,已经发布了几个非常好的替代品,它们可能值得一看。

第一个是 Volley,谷歌在 2013 年 I/O 上宣布的新网络库 https://developers.google.com/events/io/sessions/325304728

第二个是史克威尔的毕加索。Square 团队使用他们的 Android 库做了一些非常棒的工作。 http://corner.squareup.com/2013/05/picasso-one-dot-oh.html

于 2013-05-25T19:54:00.777 回答