2011-05-05 11 views
0

我有一個自定義的ListView適配器,它實現了一個ImageThreadLoader類。不幸的是,這個類沒有啓用緩存選項 - 從網上下載圖像並將它們保存爲緩存。Android:幫助修改ListView適配器與ImageLoader類

然後我發現這個LazyList項目非常有用,它的行爲與我的ImageThreadLoader類非常相似,但它能夠將圖像保存爲緩存。所以,我想實現它的ImageLoader類到我當前的自定義ListView適配器。

不幸的是,我的代碼和Lazylist的結構非常不同,導致我的嘗試發生了一些衝突。 例如,LazyList使用圖像URL的字符串數組,另一方面,我使用JSON作爲圖像URL的來源。

這就是爲什麼我需要幫助,以適應我的ListView適配器到這個ImageLoader類。

這裏是代碼:

ImageLoader的類,我想實現我的自定義的ListView適配器:

public class ImageLoader { 

    //the simplest in-memory cache implementation. This should be replaced with something like SoftReference or BitmapOptions.inPurgeable(since 1.6) 
    private HashMap<String, Bitmap> cache=new HashMap<String, Bitmap>(); 

    private File cacheDir; 

    public ImageLoader(Context context){ 
     //Make the background thead low priority. This way it will not affect the UI performance 
     photoLoaderThread.setPriority(Thread.NORM_PRIORITY-1); 

     //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(),"Android/data/LazyList"); 
     else 
      cacheDir=context.getCacheDir(); 
     if(!cacheDir.exists()) 
      cacheDir.mkdirs(); 
    } 

    final int stub_id=R.drawable.stub; 
    public void DisplayImage(String url, Activity activity, ImageView imageView) 
    { 
     if(cache.containsKey(url)) 
      imageView.setImageBitmap(cache.get(url)); 
     else 
     { 
      queuePhoto(url, activity, imageView); 
      imageView.setImageResource(stub_id); 
     }  
    } 

    private void queuePhoto(String url, Activity activity, ImageView imageView) 
    { 
     //This ImageView may be used for other images before. So there may be some old tasks in the queue. We need to discard them. 
     photosQueue.Clean(imageView); 
     PhotoToLoad p=new PhotoToLoad(url, imageView); 
     synchronized(photosQueue.photosToLoad){ 
      photosQueue.photosToLoad.push(p); 
      photosQueue.photosToLoad.notifyAll(); 
     } 

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

    private Bitmap getBitmap(String url) 
    { 
     //I identify images by hashcode. Not a perfect solution, good for the demo. 
     String filename=String.valueOf(url.hashCode()); 
     File f=new File(cacheDir, filename); 

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

     //from web 
     try { 
      Bitmap bitmap=null; 
      InputStream is=new URL(url).openStream(); 
      OutputStream os = new FileOutputStream(f); 
      Utils.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; 
     } 
    } 

    PhotosQueue photosQueue=new PhotosQueue(); 

    public void stopThread() 
    { 
     photoLoaderThread.interrupt(); 
    } 

    //stores list of photos to download 
    class PhotosQueue 
    { 
     private Stack<PhotoToLoad> photosToLoad=new Stack<PhotoToLoad>(); 

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

    class PhotosLoader extends Thread { 
     public void run() { 
      try { 
       while(true) 
       { 
        //thread waits until there are any images to load in the queue 
        if(photosQueue.photosToLoad.size()==0) 
         synchronized(photosQueue.photosToLoad){ 
          photosQueue.photosToLoad.wait(); 
         } 
        if(photosQueue.photosToLoad.size()!=0) 
        { 
         PhotoToLoad photoToLoad; 
         synchronized(photosQueue.photosToLoad){ 
          photoToLoad=photosQueue.photosToLoad.pop(); 
         } 
         Bitmap bmp=getBitmap(photoToLoad.url); 
         cache.put(photoToLoad.url, bmp); 
         Object tag=photoToLoad.imageView.getTag(); 
         if(tag!=null && ((String)tag).equals(photoToLoad.url)){ 
          BitmapDisplayer bd=new BitmapDisplayer(bmp, photoToLoad.imageView); 
          Activity a=(Activity)photoToLoad.imageView.getContext(); 
          a.runOnUiThread(bd); 
         } 
        } 
        if(Thread.interrupted()) 
         break; 
       } 
      } catch (InterruptedException e) { 
       //allow thread to exit 
      } 
     } 
    } 

    PhotosLoader photoLoaderThread=new PhotosLoader(); 

    //Used to display bitmap in the UI thread 
    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(stub_id); 
     } 
    } 

    public void clearCache() { 
     //clear memory cache 
     cache.clear(); 

     //clear SD cache 
     File[] files=cacheDir.listFiles(); 
     for(File f:files) 
      f.delete(); 
    } 

} 

從LazyList項目自定義列表視圖適配器:

public class LazyAdapter extends BaseAdapter { 

    private Activity activity; 
    private String[] data; 
    private static LayoutInflater inflater=null; 
    public ImageLoader imageLoader; 

    public LazyAdapter(Activity a, String[] d) { 
     activity = a; 
     data=d; 
     inflater = (LayoutInflater)activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE); 
     imageLoader=new ImageLoader(activity.getApplicationContext()); 
    } 

    public int getCount() { 
     return data.length; 
    } 

    public Object getItem(int position) { 
     return position; 
    } 

    public long getItemId(int position) { 
     return position; 
    } 

    public static class ViewHolder{ 
     public TextView text; 
     public ImageView image; 
    } 

    public View getView(int position, View convertView, ViewGroup parent) { 
     View vi=convertView; 
     ViewHolder holder; 
     if(convertView==null){ 
      vi = inflater.inflate(R.layout.item, null); 
      holder=new ViewHolder(); 
      holder.text=(TextView)vi.findViewById(R.id.text);; 
      holder.image=(ImageView)vi.findViewById(R.id.image); 
      vi.setTag(holder); 
     } 
     else 
      holder=(ViewHolder)vi.getTag(); 

     holder.text.setText("item "+position); 
     holder.image.setTag(data[position]); 
     imageLoader.DisplayImage(data[position], activity, holder.image); 
     return vi; 
    } 
} 

這裏是我的自定義ListView a dapter: * ProjectAdapter類 *

public class ProjectAdapter extends ArrayAdapter<Project> { 

    int resource; 
    String response; 
    Context context; 
    private final static String TAG = "MediaItemAdapter"; 

    private ImageThreadLoader imageLoader = new ImageThreadLoader(); 

    //Initialize adapter 
    public ProjectAdapter(Context context, int resource, List<Project> items) { 
     super(context, resource, items); 
     this.resource=resource; 
    } 

    @Override 
    public View getView(int position, View convertView, ViewGroup parent) 
    { 
     TextView textTitle; 
     final ImageView image; 

     Project pro = getItem(position); 

     LinearLayout projectView; 
     //Inflate the view 
     if(convertView==null) 
     { 
      projectView = new LinearLayout(getContext()); 
      String inflater = Context.LAYOUT_INFLATER_SERVICE; 
      LayoutInflater vi; 
      vi = (LayoutInflater)getContext().getSystemService(inflater); 
      vi.inflate(resource, projectView, true); 
     } 
     else 
     { 
      projectView = (LinearLayout) convertView; 
     } 

     try { 
      textTitle = (TextView)projectView.findViewById(R.id.txt_title); 
      image = (ImageView)projectView.findViewById(R.id.image); 
     } catch(ClassCastException e) { 
      Log.e(TAG, "Your layout must provide an image and a text view with ID's icon and text.", e); 
      throw e; 
     } 


     Bitmap cachedImage = null; 
     try { 
      cachedImage = imageLoader.loadImage(pro.smallImageUrl, new ImageLoadedListener() { 
      public void imageLoaded(Bitmap imageBitmap) { 
      image.setImageBitmap(imageBitmap); 
      notifyDataSetChanged();    } 
      }); 
     } catch (MalformedURLException e) { 
      Log.e(TAG, "Bad remote image URL: " + pro.smallImageUrl, e); 
     } 

     textTitle.setText(pro.project_title); 

     if(cachedImage != null) { 
      image.setImageBitmap(cachedImage); 
     } 

     return projectView; 
    } 

} 

非常感謝您!

回答

0

我在這個Code for Image Loader發佈代碼..

檢查代碼..

1.In您的活動獲得的所有圖像URL在字符串數組,並通過它..

dealAdapter = new LazyAdapter(Activityname.this,VALUE_image); 

VALUE_image包含您的圖片。

重要的是檢查你是否在清單文件

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> 

添加權限創建一個文件,即ImageLoader.class並粘貼到該鏈接

然後創建文件即Utils.class和粘貼給出圖像裝載機的代碼該鏈接中的Utils代碼。

在它檢查SD卡是否存在,如果這樣的創建在SD卡夾,並存儲壓縮格式的所有圖像和以後retrive它上面的代碼..

否則,如果沒有它存儲圖像在高速緩衝存儲器..

第一次從服務器加載圖像,下次檢查它是在Sdcard還是在高速緩存中,如果是這樣,請檢查圖像和顯示器。

檢查它..

+0

謝謝你,我已經看到你的代碼或多或少像LazyList一樣。你有沒有檢查過我的ProjectAdapter類?你可以看到它和LazyAdapter的區別。問題是,我需要應用ArrayAdapter,因爲我不會將圖像的URL存儲在字符串數組中,而是存儲在名爲Project的對象上,該對象包含我的JSON變量,用於存儲圖像URL。也許可以修改我的ProjectAdapter類嗎?謝謝 – hectichavana 2011-05-05 18:48:16