Volley ImageLoader在卷轴上重新加载加载的图像



我使用以下代码在RecyclerView中从服务器加载图像:

imageLoader = CustomVolleyRequest.getInstance(context).getImageLoader();
imageLoader.get(image_url, ImageLoader.getImageListener(holder.title_img, R.drawable.reads, android.R.drawable.ic_dialog_alert));
holder.title_img.setImageUrl(image_url, imageLoader);

问题是,当我再次向上滚动时,加载的图像会被重新加载。。如何避免这种情况。。。

您应该在设备中缓存映像以防止再次加载映像。

创建一个名为LruBitmapCache.java的类,并添加以下代码。这个类负责在磁盘上缓存网络映像。

LruBitmapCache.java

import com.android.volley.toolbox.ImageLoader.ImageCache;
import android.graphics.Bitmap;
import android.support.v4.util.LruCache;
public class LruBitmapCache extends LruCache<String, Bitmap> implements
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 sizeInKiloBytes) {
super(sizeInKiloBytes);
}
@Override
protected int sizeOf(String key, Bitmap value) {
return value.getRowBytes() * value.getHeight() / 1024;
}
@Override
public Bitmap getBitmap(String url) {
return get(url);
}
@Override
public void putBitmap(String url, Bitmap bitmap) {
put(url, bitmap);
}
}

创建名为AppController.java的类并粘贴以下内容。这是一个单例类,用于初始化所需类的全局实例。所有与截击相关的对象都在这里初始化:

import YourPakageName.LruBitmapCache;
import android.app.Application;
import android.text.TextUtils;
import com.android.volley.Request;
import com.android.volley.RequestQueue;
import com.android.volley.toolbox.ImageLoader;
import com.android.volley.toolbox.Volley;
public class AppController extends Application {
public static final String TAG = AppController.class.getSimpleName();
private RequestQueue mRequestQueue;
private ImageLoader mImageLoader;
LruBitmapCache mLruBitmapCache;
private static AppController mInstance;
@Override
public void onCreate() {
super.onCreate();
mInstance = this;
}
public static synchronized AppController getInstance() {
return mInstance;
}
public RequestQueue getRequestQueue() {
if (mRequestQueue == null) {
mRequestQueue = Volley.newRequestQueue(getApplicationContext());
}
return mRequestQueue;
}
public ImageLoader getImageLoader() {
getRequestQueue();
if (mImageLoader == null) {
getLruBitmapCache();
mImageLoader = new ImageLoader(this.mRequestQueue, mLruBitmapCache);
}
return this.mImageLoader;
}
public LruBitmapCache getLruBitmapCache() {
if (mLruBitmapCache == null)
mLruBitmapCache = new LruBitmapCache();
return this.mLruBitmapCache;
}
public <T> void addToRequestQueue(Request<T> req, String tag) {
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 (mRequestQueue != null) {
mRequestQueue.cancelAll(tag);
}
}
}

现在打开你的AndroidManifest.xml文件,在标签中添加Application.java类:

<application
android:name="YourPakageName.app.AppController"> ....</application>

之后转到您的适配器并添加以下代码:

private Context context;
ImageLoader imageLoader = 
YourPakageName.AppController.getInstance().getImageLoader();
private RequestQueue queue;
private LruCache<Integer, Bitmap> imageCache;

和:

public MyCustommAdapter(Context context, int resource, List<YourModel> objects) {
super(context, resource, objects);
this.context = context;
this.postList = objects;
final int maxMemory = (int)(Runtime.getRuntime().maxMemory() /1024);
final int cacheSize = maxMemory / 5;
imageCache = new LruCache<Integer, Bitmap>(cacheSize);
queue = Volley.newRequestQueue(context);
}

现在,您只需获取url图像并在列表视图中显示即可:

imageLoader.get(image_url, new ImageLoader.ImageListener() {
@Override
public void onErrorResponse(VolleyError error) {
//Log.e(TAG, "Image Load Error: " + error.getMessage());
}
@Override
public void onResponse(ImageLoader.ImageContainer response, boolean arg1) {
if (response.getBitmap() != null) {
// load image into imageview
holder.title_img.setImageBitmap(response.getBitmap());
}
}
});

官方文档建议,当需要编写LruBitmapCache.java时,图像的内存缓存核心在以下代码段中:

final int maxMemory = (int) (Runtime.getRuntime().maxMemory() / 1024);
// Use 1/8th of the available memory for this memory cache.
final int cacheSize = maxMemory / 8;

Android缓存位图文档特别指出

注意:在这个例子中,八分之一的应用程序内存被分配给我们的缓存。在普通/hdpi设备上,这是大约4MB(32/8)的最小值。在分辨率为800x480的设备上,一个充满图像的全屏GridView将使用大约1.5MB(800*480*4字节),因此这将在内存中缓存至少大约2.5页的图像。

我做了一个小实验,就像Khaled Rostampour建议的那样:

maxMemory / 5;

但是,将maxMemory设置为较低的数字会更好地获得流畅的体验,就像Facebook应用程序的体验一样。

我已经用这个类似Facebook的应用程序做了一个基本的测试,这是一个很好的Volley教程,它实现了Khalid的建议,但当maxMemory/8甚至使用maxMemory/3时,我在试图实现理想的平滑度时遇到了困难。

我终于选择了设置:

maxMemory / 2;

你猜怎么着,这种体验模仿了Facebook应用程序的流畅性(甚至更好)。

因此,根据您的需要,您可以在应用程序的各个部分中为图像缓存例程分配多少内存。

在构建应用程序时要考虑的最后一个决定因素是用户体验因素,就像我提到的例子一样。这是我在安卓开发的第三周,我意识到开发人员需要平衡性能和用户体验,我发现这是一个需要记住的好设计模式,我相信,即使是我们经常使用的经过验证的应用程序也能做到这一点。

图像不会从URL重新加载,而是从缓存重新加载。recyclereview将图像保存在内存中,并"回收"视图以节省内存。如果您不想回收需要使用的视图,例如,ListView而不是RecyclerView。

最新更新