如何正确设置Volley以从URL下载图像

时间:2014-07-28 03:47:01

标签: android caching bitmap android-volley

我知道Volley应该简单地下载和缓存图像,但我已经挣扎了几个小时才能正确实现它。我已经浏览了网络以及有关凌空的stackoverflow上的许多文章,但我发现的所有示例似乎都不适合我。

我只想使用volley来下载和缓存来自给定URL的图像,而不是进行任何HTTP JSON REST处理。只需要获取给定的URL,下载位图并将它们设置为imageview,然后将它们添加到缓存中。

这是我迄今为止的最新尝试。 如何正确加载和缓存图像?

if (data.getImageUrl() != null) {
        try {

            holder.thumbnail.setTag(data.getImageUrl());

        Cache cache = ImgController.getInstance().getRequestQueue().getCache();
        Cache.Entry entry = cache.get(data.getImageUrl());

            if (entry != null) {
                try {
                    String cImg = new String(entry.data, "UTF-8");
                    LruBitmapCache bitmapCache = new LruBitmapCache();
                    holder.thumbnail.setImageBitmap(bitmapCache.getBitmap(cImg));
                } catch (UnsupportedEncodingException e) {
                    e.printStackTrace();
                }

            } else {

                ImageLoader imageLoader = ImgController.getInstance().getImageLoader();

                imageLoader.get(data.getImageUrl(), new ImageListener() {

                    @Override
                    public void onErrorResponse(VolleyError error) {

                        holder.thumbnail.setImageResource(R.drawable.filler_icon);

                    }

                    @Override
                    public void onResponse(ImageLoader.ImageContainer response, boolean arg1) {
                        if (response.getBitmap() != null) {
                            // load image into imageview
                            holder.thumbnail.setImageBitmap(response.getBitmap());

                        }
                    }
                });
            }

            return convertView;
        } catch (Exception e) {
            e.printStackTrace();
            Log.v(DEBUG_TAG, "no image: ", e);
            holder.thumbnail.setImageResource(R.drawable.filler_icon);


        }
    }else {
        return null;
    }


    return convertView;
}

当我运行它时,我得到一个指向此行的NullPointerException

Cache cache = ImgController.getInstance().getRequestQueue().getCache();

我已设置以下单例类来处理请求

public class ImgController extends Application {

public static final String TAG = ImgController.class.getSimpleName();
private RequestQueue requestQueue;
private ImageLoader imageLoader;

private static ImgController instance;

@Override
public void onCreate() {
    super.onCreate();
    instance = this;

}
public static synchronized ImgController getInstance(){
    return instance;
}
public RequestQueue getRequestQueue(){
    if(requestQueue == null){
        requestQueue = Volley.newRequestQueue(getApplicationContext());
    }
    return this.requestQueue;
}
public ImageLoader getImageLoader(){
    getRequestQueue();
    if(imageLoader ==  null){
        imageLoader = new ImageLoader(this.requestQueue, new LruBitmapCache());
        }

    return this.imageLoader;
}
public <T> void addToRequestQueue(Request<T> req, String tag) {
    // set the default tag if tag is empty
    req.setTag(TextUtils.isEmpty(tag) ? TAG : tag);
    getRequestQueue().add(req);
}

public <T> void addToRequestQueue(Request<T> req) {
    req.setTag(TAG);
    getRequestQueue().add(req);
}

public void cancelPendingRequests(Object tag) {
    if (requestQueue != null) {
        requestQueue.cancelAll(tag);
    }
}

}

以及以下LruBitmapCache类

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

public static int getDefaultLruCacheSize(){
    final int maxMemory = (int) (Runtime.getRuntime().maxMemory() / 1024);
    final int cacheSize = maxMemory / 8;

    return cacheSize;
}

public LruBitmapCache() {
    this(getDefaultLruCacheSize());
}
public LruBitmapCache(int maxSize) {
    super(maxSize);
}

@Override
public Bitmap getBitmap(String url) {
    return get(url);
}

@Override
public void putBitmap(String url, Bitmap bitmap) {
    put (url, bitmap);
}

}

5 个答案:

答案 0 :(得分:8)

(抱歉英语能力差^^;)

  

Volley应该让人无意识地下载和缓存图像

是啊!排球非常简单。你不需要考虑缓存命中,图像加载等......

只需使用NetworkImageView即可。贝鲁斯就是榜样。

layout_example.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:paddingBottom="@dimen/activity_vertical_margin"
    tools:context=".MainActivity">

    <com.android.volley.toolbox.NetworkImageView
            android:id="@+id/photo"
            android:adjustViewBounds="true"
            android:scaleType="fitCenter"
            android:layout_width="match_parent"
            android:layout_height="match_parent"/>

</RelativeLayout>

MainActivity.java

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.layout_example);
    NetworkImageView nv = (NetworkImageView) findViewById(R.id.photo);
    nv.setDefaultImageResId(R.drawable.default_image); // image for loading...
    nv.setImageUrl(imageUrl, ImgController.getInstance().getImageLoader()); //ImgController from your code.
}

NetworkImageView会自动从后台队列加载图像,并在分离此视图时取消请求using ImageLoader。并且ImageLoader 会自动使用内存直通缓存和磁盘缓存。 NetworkImageView是最适合您的解决方案。

其他信息

NetworkImageView
       |
  ImageLoader (uses `LruBitmapCache` you implemented.)
       |
 RequestQueue (uses `DiskBasedCache`. it is already implemented in volley.)

答案 1 :(得分:7)

Volley可以使用图像请求的回调,您可以使用下面的代码。

    ImageView iv = null; /*Attach the Pointer for ImageView*/
    RequestQueue requestAdministrator = null; /*Attach the Pointer for Volley*/

    ImageRequest ir = new ImageRequest(url, new Response.Listener<Bitmap>() {
        @Override
        public void onResponse(Bitmap response) {
            // callback
            iv.setImageBitmap(response);
        }
    }, 100, 100, null, null);
    // 100 is your custom Size before Downloading the Image.
    requestAdministrator.add(ir);

答案 2 :(得分:1)

ImageRequest 已弃用,因此我按以下方式执行此操作:

第1步:首先制作应用课程

public class YourApplicationClass extends Application {
    private static YourApplicationClass sInstance;
    private RequestQueue mRequestQueue;
    private ImageLoader mImageLoader;

    public static YourApplicationClass getInstance(){
        return sInstance;
    }

    @Override
    public void onCreate() {
        super.onCreate();
        sInstance = this;

        mRequestQueue = Volley.newRequestQueue(this);
        mImageLoader = new ImageLoader(this.mRequestQueue, new ImageLoader.ImageCache() {

            private final LruCache<String, Bitmap> mCache = new LruCache<String, Bitmap>(10);

            public Bitmap getBitmap(String url) {
                return mCache.get(url);
            }

            @Override
            public void putBitmap(String url, Bitmap bitmap) {
                mCache.put(url, bitmap);
            }

        });
    }

    public RequestQueue getRequestQueue(){
        return mRequestQueue;
    }

    public ImageLoader getImageLoader(){
        return mImageLoader;
    }
}

第2步:现在,从任何活动片段

按照以下方式发出图像请求
YourApplicationClass.getInstance().getImageLoader().get(image_url, new ImageLoader.ImageListener() {
                @Override
                public void onResponse(ImageLoader.ImageContainer imageContainer, boolean b) {
                 Bitmap bitmap = imageContainer.getBitmap();
                 //use bitmap 
                }

                @Override
                public void onErrorResponse(VolleyError volleyError) {

                }
            });

答案 3 :(得分:0)

答案 4 :(得分:0)

我有一个更简单的解决方案,用于显示来自url的图像并将其存储在缓存中。无需添加其他类,只需添加MainActivity。 可能它会帮助某人...

这是我的XML,只显示ImageView

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.example.natalie.volley.MainActivity">


    <ImageView
        android:id="@+id/ivImageView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_margin="50dp"/>

</android.support.constraint.ConstraintLayout>

这是我的MainAvtivity.java:

  import android.graphics.Bitmap;
    import android.support.v7.app.AppCompatActivity;
    import android.os.Bundle;
    import android.widget.ImageView;

    import com.android.volley.RequestQueue;
    import com.android.volley.Response;
    import com.android.volley.VolleyError;
    import com.android.volley.toolbox.ImageRequest;
    import com.android.volley.toolbox.Volley;

    public class MainActivity extends AppCompatActivity {

        private String url = "http://kingofwallpapers.com/picture/picture-010.jpg";
        ImageView ivImageView;
        RequestQueue mRequestQueue;

        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            ivImageView = (ImageView)findViewById(R.id.ivImageView);
            mRequestQueue = Volley.newRequestQueue(this.getApplicationContext());
            ImageRequest imageRequest = new ImageRequest(url, new BitmapListener(), 0, 0, null, null, new MyErrorListener());

            mRequestQueue.add(imageRequest);
        }

        private class BitmapListener implements Response.Listener<Bitmap> {
            @Override
            public void onResponse(Bitmap response) {
// response = your url's bitmap
                ivImageView.setImageBitmap(response);

            }
        }

        private class MyErrorListener implements Response.ErrorListener {
            @Override
            public void onErrorResponse(VolleyError error) {
//store a default image if connection failed
                ivImageView.setImageResource(R.drawable.error_icon);
            }
        }
    }

不要忘记在Manifest.xml中添加<uses-permission android:name="android.permission.INTERNET" /> 和build.gradle依赖项中的compile 'com.android.volley:volley:1.0.0'