2012-03-12 58 views
0

我按照程序here爲我設置了一個簡單的AsyncTask Image下載器/加載器。我從適配器的GetView中調用下載函數。因此,每當我向上或向下滾動時,一旦視圖退出屏幕,圖像就會消失,只有當我滾動回該項目時纔會再次設置。如何阻止這一點,並且一旦我下載/緩存了所有圖像,就可以設置它。我不希望每次都重置我的ImageView。Imageview在Android中使用AsyncTask設置多個時間

這是的ImageManager:

import java.io.File; 
import java.io.FileOutputStream; 
import java.net.URL; 
import java.util.HashMap; 
import java.util.Stack; 

import android.R; 
import android.app.Activity; 
import android.content.Context; 
import android.graphics.Bitmap; 
import android.graphics.BitmapFactory; 
import android.widget.ImageView; 



public class ImageManager { 
     private HashMap<String, Bitmap> imageMap = new HashMap<String, Bitmap>(); 
     private File cacheDir; 
     public Thread imageLoaderThread = new Thread() ; 
     public ImageQueue imageQueue = new ImageQueue(); 
     public ImageManager(Context context) { 
     // Make background thread low priority, to avoid affecting UI performance 
     imageLoaderThread.setPriority(Thread.NORM_PRIORITY-1); 

     // Find the dir to save cached images 
     String sdState = android.os.Environment.getExternalStorageState(); 
     if (sdState.equals(android.os.Environment.MEDIA_MOUNTED)) { 
      File sdDir = android.os.Environment.getExternalStorageDirectory();  
      cacheDir = new File(sdDir,"data/codehenge"); 
     } 
     else 
      cacheDir = context.getCacheDir(); 

     if(!cacheDir.exists()) 
      cacheDir.mkdirs(); 
     } 


     private void queueImage(String url, ImageView imageView) { 
      // This ImageView might have been used for other images, so we clear 
      // the queue of old tasks before starting. 
      imageQueue.Clean(imageView); 
      ImageRef p=new ImageRef(url, imageView); 

      synchronized(imageQueue.imageRefs) { 
      imageQueue.imageRefs.push(p); 
      imageQueue.imageRefs.notifyAll(); 
      } 

      // Start thread if it's not started yet 
      if(imageLoaderThread.getState() == Thread.State.NEW) 
      imageLoaderThread.start(); 
     } 




    private class ImageRef { 
      public String url; 
      public ImageView imageView; 

      public ImageRef(String u, ImageView i) { 
      url=u; 
      imageView=i; 
      } 
     } 

    private class ImageQueue { 
      private Stack<ImageRef> imageRefs = new Stack<ImageRef>(); 

      //removes all instances of this ImageView 
      public void Clean(ImageView view) { 
      for(int i = 0 ;i < imageRefs.size();) { 
       if(imageRefs.get(i).imageView == view) 
       imageRefs.remove(i); 
       else ++i; 
      } 
      } 
    } 

    private class ImageQueueManager implements Runnable { 
      @Override 
      public void run() { 
      try { 
       while(true) { 
       // Thread waits until there are images in the 
       // queue to be retrieved 
       if(imageQueue.imageRefs.size() == 0) { 
        synchronized(imageQueue.imageRefs) { 
        imageQueue.imageRefs.wait(); 
        } 
       } 

       // When we have images to be loaded 
       if(imageQueue.imageRefs.size() != 0) { 
        ImageRef imageToLoad; 

        synchronized(imageQueue.imageRefs) { 
        imageToLoad = imageQueue.imageRefs.pop(); 
        } 

        Bitmap bmp = getBitmap(imageToLoad.url); 
        imageMap.put(imageToLoad.url, bmp); 
        Object tag = imageToLoad.imageView.getTag(); 

        // Make sure we have the right view - thread safety defender 
        if(tag != null && ((String)tag).equals(imageToLoad.url)) { 
        BitmapDisplayer bmpDisplayer = 
         new BitmapDisplayer(bmp, imageToLoad.imageView); 

        Activity a = 
         (Activity)imageToLoad.imageView.getContext(); 

        a.runOnUiThread(bmpDisplayer); 
        } 
       } 

       if(Thread.interrupted()) 
        break; 
       } 


      } 
      catch (InterruptedException e) {} 
      } 



private Bitmap getBitmap(String url) { 
     String filename = String.valueOf(url.hashCode()); 
     File f = new File(cacheDir, filename); 

     // Is the bitmap in our cache? 
     Bitmap bitmap = BitmapFactory.decodeFile(f.getPath()); 
     if(bitmap != null) return bitmap; 

     // Nope, have to download it 
     try { 
     bitmap = 
     BitmapFactory.decodeStream(new URL(url).openConnection().getInputStream()); 
     // save bitmap to cache for later 
     writeFile(bitmap, f); 

     return bitmap; 
     } catch (Exception ex) { 
     ex.printStackTrace(); 
     return null; 
     } 
    } 

    private void writeFile(Bitmap bmp, File f) { 
     FileOutputStream out = null; 

     try { 
     out = new FileOutputStream(f); 
     bmp.compress(Bitmap.CompressFormat.PNG, 80, out); 
     } catch (Exception e) { 
     e.printStackTrace(); 
     } 
     finally { 
     try { if (out != null) out.close(); } 
     catch(Exception ex) {} 
     } 
    } 
} 

    public void displayImage(String url, Activity activity, ImageView imageView) { 


     if(imageMap.containsKey(url)) { 

      Bitmap bitmapToShow = imageMap.get(url); 

      if(bitmapToShow != null) { 
      //> Image was cached well 
      imageView.setImageBitmap(bitmapToShow); 
      return; 
      } 
      } 

      //> Image was cached failed 
     else { 
      imageView.setImageResource(R.drawable.btn_radio); 
      queueImage(url,imageView); 
      return; 
      } 



     } 

    private class BitmapDisplayer implements Runnable { 
      Bitmap bitmap; 
      ImageView imageView; 

      public BitmapDisplayer(Bitmap b, ImageView i) { 
      bitmap=b; 
      imageView=i; 
      } 

      public void run() { 
      if(bitmap != null) 
       imageView.setImageBitmap(bitmap); 
      else 
       imageView.setImageResource(R.drawable.spinner_background); 
      } 
     } 


} 

筆者認爲:

if(v == null){ 
     LayoutInflater li = (LayoutInflater)c.getSystemService(Context.LAYOUT_INFLATER_SERVICE); 
     v = li.inflate(R.layout.list_item,null); 
     holder = new ViewHolder(); 

    holder.name = (TextView)v.findViewById(R.id.name); 
    holder.text = (TextView)v.findViewById(R.id.text); 
    holder.displayPic = (ImageView)v.findViewById(R.id.DisplayPicture); 
    v.setTag(holder); 

    } 

    else 
    { 
     holder = (ViewHolder)v.getTag(); 

     obj = objs.get(position); 
     if (obj != null) 
     { 
      holder.name.setText(obj.Name); 
      holder.text.setText(""+obj.snippet); 
      holder.displayPic.setTag(obj.ImageUrl); 
      imageManager.displayImage(obj.ImageUrl, activity, holder.displayPic); 

     } 
} 

回答

2

getView方法每次意見需要是diplayed調用,如下載圖像的這種方法下載圖像每個視圖,所以它每次都會用新圖像加載視圖,爲了避免這種情況,您需要實現某種類型的緩存,爲了實現緩存,您可以使用可能具有位圖的hashmap或arraylist,但可能會導致OutOfMemory導致列表大小不正常,所以你可以實現緩存文件系統,請按照示例來實現緩存:

http://codehenge.net/blog/2011/06/android-development-tutorial-asynchronous-lazy-loading-and-caching-of-listview-images/

+0

+1好的答案。 – Dharmendra 2012-03-12 04:40:56

+0

我試過了。沒有得到任何圖像。 – Hick 2012-03-12 07:47:29

+0

請分享你已經試過的代碼 – jeet 2012-03-12 07:57:39

相關問題