2015-10-07 76 views
0

目前我正在使用android。我尝试加载一些textview和imageview的列表视图。但是,一些listview中的元素的图像浏览并不能显示正确的图像。一些元素的图像浏览也没有显示图片,同时在网络版中所有这些都显示正确。我检查了网址,并没有问题。所以我想这个问题是在图像加载器类。下面是我用来显示图片的图片加载器类。有时android图像加载器加载错误的图像或不加载图像

ImageLoader.java

public class ImageLoader { 

MemoryCache memoryCache=new MemoryCache(); 
FileCache fileCache; 
private Map<ImageView, String> imageViews=Collections.synchronizedMap(new WeakHashMap<ImageView, String>()); 
ExecutorService executorService; 

public ImageLoader(Context context){ 
    fileCache=new FileCache(context); 
    executorService=Executors.newFixedThreadPool(5); 
} 

final int stub_id = R.drawable.no_picture_resize; 
public void DisplayImage(String url, ImageView imageView) 
{ 
    imageViews.put(imageView, url); 
    //System.out.println("URl = "+url); 
    Bitmap bitmap=memoryCache.get(url); 
    if(bitmap!=null) 
     imageView.setImageBitmap(bitmap); 
    else 
    { 
     queuePhoto(url, imageView); 
     imageView.setImageResource(stub_id); 
    } 
} 

private void queuePhoto(String url, ImageView imageView) 
{ 
    PhotoToLoad p=new PhotoToLoad(url, imageView); 
    executorService.submit(new PhotosLoader(p)); 
} 

private Bitmap getBitmap(String url) 
{ 
    File f=fileCache.getFile(url); 

    //from SD cache 
    Bitmap b = decodeFile(f); 
    if(b!=null) 
     return b; 

    //from web 
    try { 
     Bitmap bitmap=null; 
     URL imageUrl = new URL(url); 
     HttpURLConnection conn = (HttpURLConnection)imageUrl.openConnection(); 
     conn.setConnectTimeout(100000); 
     conn.setReadTimeout(100000); 
     conn.setInstanceFollowRedirects(true); 
     InputStream is=conn.getInputStream(); 
     OutputStream os = new FileOutputStream(f); 
     Utility.CopyStream(is, os); 
     os.close(); 
     bitmap = decodeFile(f); 
     return bitmap; 
    } catch (Exception ex){ 
     ex.printStackTrace(); 
     return null; 
    } 
} 

//decodes image and scales it to reduce memory consumption 
private Bitmap decodeFile(File f){ 
    try { 
     //decode image size 
     BitmapFactory.Options o = new BitmapFactory.Options(); 
     o.inJustDecodeBounds = true; 
     BitmapFactory.decodeStream(new FileInputStream(f),null,o); 

     //Find the correct scale value. It should be the power of 2. 
     final int REQUIRED_SIZE=70; 
     int width_tmp=o.outWidth, height_tmp=o.outHeight; 
     int scale=1; 
     while(true){ 
      if(width_tmp/2<REQUIRED_SIZE || height_tmp/2<REQUIRED_SIZE) 
       break; 
      width_tmp/=2; 
      height_tmp/=2; 
      scale*=2; 
     } 

     //decode with inSampleSize 
     BitmapFactory.Options o2 = new BitmapFactory.Options(); 
     o2.inSampleSize=scale; 
     return BitmapFactory.decodeStream(new FileInputStream(f), null, o2); 
    } catch (FileNotFoundException e) {} 
    return null; 
} 

//Task for the queue 
private class PhotoToLoad 
{ 
    public String url; 
    public ImageView imageView; 
    public PhotoToLoad(String u, ImageView i){ 
     url=u; 
     imageView=i; 
    } 
} 

class PhotosLoader implements Runnable { 
    PhotoToLoad photoToLoad; 
    PhotosLoader(PhotoToLoad photoToLoad){ 
     this.photoToLoad=photoToLoad; 
    } 

    @Override 
    public void run() { 
     if(imageViewReused(photoToLoad)) 
      return; 
     Bitmap bmp=getBitmap(photoToLoad.url); 
     memoryCache.put(photoToLoad.url, bmp); 
     if(imageViewReused(photoToLoad)) 
      return; 
     BitmapDisplayer bd=new BitmapDisplayer(bmp, photoToLoad); 
     Activity a=(Activity)photoToLoad.imageView.getContext(); 
     a.runOnUiThread(bd); 
    } 
} 

boolean imageViewReused(PhotoToLoad photoToLoad){ 
    String tag=imageViews.get(photoToLoad.imageView); 
    if(tag==null || !tag.equals(photoToLoad.url)) 
     return true; 
    return false; 
} 

//Used to display bitmap in the UI thread 
class BitmapDisplayer implements Runnable 
{ 
    Bitmap bitmap; 
    PhotoToLoad photoToLoad; 
    public BitmapDisplayer(Bitmap b, PhotoToLoad p){bitmap=b;photoToLoad=p;} 
    public void run() 
    { 
     if(imageViewReused(photoToLoad)) 
      return; 
     if(bitmap!=null) 
      photoToLoad.imageView.setImageBitmap(bitmap); 
     else 
      photoToLoad.imageView.setImageResource(stub_id); 
    } 
} 

public void clearCache() { 
    memoryCache.clear(); 
    fileCache.clear(); 
} 

}

FileCache.java

public class FileCache { 

private File cacheDir; 

public FileCache(Context context){ 
    //Find the dir to save cached images 
    if (android.os.Environment.getExternalStorageState().equals(android.os.Environment.MEDIA_MOUNTED)) 
     cacheDir=new File(android.os.Environment.getExternalStorageDirectory(),"TempImages"); 
    else 
     cacheDir=context.getCacheDir(); 
    if(!cacheDir.exists()) 
     cacheDir.mkdirs(); 
} 

public File getFile(String url){ 
    String filename=String.valueOf(url.hashCode()); 
    File f = new File(cacheDir, filename); 
    return f; 

} 

public void clear(){ 
    File[] files=cacheDir.listFiles(); 
    if(files==null) 
     return; 
    for(File f:files) 
     f.delete(); 
} 

}

MemoryCache.java

public class MemoryCache { 
private Map<String, SoftReference<Bitmap>> cache=Collections.synchronizedMap(new HashMap<String, SoftReference<Bitmap>>()); 

public Bitmap get(String id){ 
    if(!cache.containsKey(id)) 
     return null; 
    SoftReference<Bitmap> ref=cache.get(id); 
    return ref.get(); 
} 

public void put(String id, Bitmap bitmap){ 
    cache.put(id, new SoftReference<Bitmap>(bitmap)); 
} 

public void clear() { 
    cache.clear(); 
} 

}

我从http://www.androidhive.info/2012/07/android-loading-image-from-url-http/得到那些类。请尽快帮忙。谢谢。

+1

尝试[Picasso](http://square.github.io/picasso/)用于加载和缓存图像.. – Emil

+1

我强烈建议使用图像加载框架,如Glide(https://github.com/bumptech /滑行)。 正确处理ListView中的图像可能相当复杂。 –

回答

0

回收视图的问题与在ListView中所做的一样,偶尔会在ImageView被回收时取消加载图像的请求。会发生什么情况是ImageView加载先前的请求,而不是/通过当前请求,导致显示不正确的图像。

您不应该尝试创建自己的解决方案,而应该使用已经可用的库中的一个处理此特定细微差别以及各种其他事情(调整大小以减少内存等)。

我目前最喜欢的是Glide(下降),但其他选项是Picasso(下降)和Fresco(复杂)。