質問

I am using NetworkImageView to show some covers downloaded from a remote URL and I successfully manage to cache and show them, but I want to let users set their own cover images if they want. I tried to use setImageUrl method with Uri.fromFile(mCoverFile).toString() as arguments, but it doesn't work. Since it is a mix of remote and local images I can't switch to regular ImageViews, so I was wondering if there's any way to enable loading of local images.

I am of course aware of the ImageView's setImageBitmap method, but NetworkImageView automatically resizes the created Bitmap and also prevents View recycling in GridViews and ListViews.

UPDATE: njzk2's answer did the trick. To autoresize the Bitmap according to your View size, then just copy the ImageRequest.doParse method from Volley's source.

役に立ちましたか?

解決

NetworkImageView uses ImageLoader, which in turn uses an ImageCache.

You can provide a custom ImageCache with your images, provided you use the same mechanism for keys:

 return new StringBuilder(url.length() + 12).append("#W").append(maxWidth)
            .append("#H").append(maxHeight).append(url).toString();

url is not tested before the actual request would be done, so no issue here.

Typically, your 'cache' could look like :

public class MyCache implements ImageLoader.ImageCache {

    @Override
    public Bitmap getBitmap(String key) {
        if (key.contains("file://")) {
            return BitmapFactory.decodeFile(key.substring(key.indexOf("file://") + 7));
        } else {
            // Here you can add an actual cache
            return null;
        }
    }
    @Override
    public void putBitmap(String key, Bitmap bitmap) {
        // Here you can add an actual cache
    }
}

You use it like :

imageView.setImageUrl(Uri.fromFile(mCoverFile).toString(), new MyCache());

(This has not been actually tested and there may be some adjustments to do)

他のヒント

Thank you for your answer. I wrote some code based on your help.

usage: just use LocalImageCache.class as Cache. No more code to change.

private ImageLoader mLocalImageLoader;

mLocalImageLoader = new ImageLoader(mRequestQueue,
            new LocalImageCache(mCtx));

NetworkImageView test = (NetworkImageView) findViewById(R.id.iv_test);  

test.setImageUrl("/storage/emulated/0/DCIM/Philm/2017_03_24_01_.png", MySingleton.getInstance(this.getApplicationContext()).getLocalImageLoader());

public class LocalImageCache extends LruCache<String, Bitmap> implements ImageLoader.ImageCache {

public LocalImageCache(int maxSize) {
    super(maxSize);
}

public LocalImageCache(Context ctx) {
    this(getCacheSize(ctx));
}

@Override
public Bitmap getBitmap(String key) {
    key = key.substring(key.indexOf("/"));
    Bitmap result = get(key);
    Log.d("TAG", key);
    if (result == null) {
        Bitmap temp =  BitmapFactory.decodeFile(key);
        put(key, temp);
        return temp;
    } else {
        return result;
    }
}

@Override
public void putBitmap(String key, Bitmap bitmap) {
    // Here you can add an actual cache
    // Never touch here
}

// 默认屏幕5倍的图片缓存
// Returns a cache size equal to approximately three screens worth of images.
public static int getCacheSize(Context ctx) {
    final DisplayMetrics displayMetrics = ctx.getResources().
            getDisplayMetrics();
    final int screenWidth = displayMetrics.widthPixels;
    final int screenHeight = displayMetrics.heightPixels;
    // 4 bytes per pixel
    final int screenBytes = screenWidth * screenHeight * 4;

    return screenBytes * 5;
}

@Override
protected int sizeOf(String key, Bitmap value) {
    return value.getRowBytes() * value.getHeight();
}

}

NetworkImageView extends ImageView. You should be able to use the same methods as a regular ImageView

image.setImageResource(R.drawable.my_image);

or

imageView.setImageBitmap(BitmapFactory.decodeFile(imagePath)); 
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top