2

インターネットから画像をダウンロードしてキャッシュディレクトリにキャッシュする小さなコードを書きました。 セカンダリ スレッドで実行されます。

{

    String hash = md5(urlString);
    File f = new File(m_cacheDir, hash);

    if (f.exists())
    {
        Drawable d = Drawable.createFromPath(f.getAbsolutePath());
        return d;
    }

    try {
        InputStream is = download(urlString);
        Drawable drawable = Drawable.createFromStream(is, "src");

        if (drawable != null)
        {
            FileOutputStream out = new FileOutputStream(f);
            Bitmap bitmap = ((BitmapDrawable)drawable).getBitmap();
            bitmap.compress(CompressFormat.JPEG, 90, out);
        }

        return drawable;
    } catch (Throwable e) { }

    return null;
}

このコードを使用して ListView アイテム内に画像をロードすると、正常に動作します。最初のif(ディスクから画像をロードする場所)を削除すると、スムーズに実行されます(そして毎回画像をダウンロードします!)。そのままにしておくと、リストビューをスクロールすると、ディスクからの画像の読み込み中にラグが発生します。なぜですか?

4

2 に答える 2

0

「なぜ」という質問に答えるために、logcat で多くの gc() メッセージを使用してこれを経験しました。Android は、ディスクからファイルをデコードする前にメモリを割り当てます。これにより、ガベージ コレクションが発生する可能性があり、すべてのスレッドでパフォーマンスが低下します。jpeg をエンコードする場合も、おそらく同じことが起こります。

デコード部分については、Android に画像をその場でデコードさせるビットマップがある場合は、既存のビットマップを再利用してみることができます。次のスニペットをご覧ください。

final BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = inSampleSize;
options.inJustDecodeBounds = false;
options.inMutable = true;
if (oldBitmap != null) {
    options.inBitmap = oldBitmap;
}
return BitmapFactory.decodeFile(f.getAbsolutePath(), options);
于 2014-08-28T15:10:28.303 に答える