2016-06-13 45 views
0

我使用下面的代码加载从服务器镜像在RecyclerView重装加载的图像:凌空ImageLoader的上滚动

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

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

回答

-1

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

+0

如果缓存的图像重用,那么shud不是一个滞后。此外,当我断开中间的互联网时,图像抖动以任何方式再现。但是,这些都不是这样的... –

+0

甚至listview可以回收视图! –

+0

普通列表视图不回收视图,Recycler View是ListView的一个扩展,它向您显示onBindViewHolder,并且此方法创建或回收视图。 – rik194

0

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

创建一个名为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()); 
        } 
       } 
      }); 
+0

为什么我们需要齐齐写出所有这些。排球应该提供内置的功能来做到这一点..无论如何,如果我能得到时间,我会尝试你的代码一次..现在我正在尝试毕加索图书馆... –

0

的官方文档显示,当需要写入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; 

的AndroidCaching Bitmap documentation特别指出

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

我做了一个小实验像什么哈立德Rostampour建议:

maxMemory/5; 

但maxMemory设置为较低的数字是一个流畅的体验,就像Facebook的应用程序体验更好。

我用这个Facebook-like app做了一个基本测试,这是一个很好的教程,在Volley上有一个很好的教程,它实现了Khalid建议的内容,但是当maxMemory/8甚至maxMemory时,我都遇到了滚动来试图达到理想的平滑度/ 3.

我终于做出了选择设置:

maxMemory/2; 

你猜怎么着,经验模仿了Facebook应用程序的平滑度(甚至更好)。

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

构建应用时需要考虑的最终决定因素就像我参考的示例用户体验因子。我的第三周在android开发中,我意识到开发人员需要在性能和用户体验之间取得平衡,我发现这是一个很好的设计模式,我相信,即使是经过验证的应用程序,我们经常使用它一样。