Android二级缓存加载图片实现照片墙功能

Android二级缓存加载图片实现照片墙功能,第1张

概述实现二级缓存加载图片的功能,在使用DiskLruCache时,需先在工程中添加名为libcore.io的包,并将DiskLruCache.Java文件放进去。DiskLruCache直接百度下载即可。

实现二级缓存加载图片的功能,在使用diskLruCache时,需先在工程中添加名为libcore.io的包,并将diskLruCache.Java文件放进去。diskLruCache直接百度下载即可。

在GrIDVIEw的适配器中,为ImageVIEw添加图片时,先从内存缓存中加载,内存中无缓存的话则在磁盘缓存中加载,磁盘缓存也没有的话开启线程下载,然后将下载的图片缓存到磁盘,内存中。下载的图片最好先进行压缩,文章最后给出了压缩代码,但本例中并未实现压缩。

/*二级缓存实现图片墙功能,先在内存中加载缓存,内存中无缓存的话到磁盘缓存中加载,仍然没有的话开启线程下载图片,下载后缓存到磁盘中,然后缓存到内存中*/

public class ErJiHuanCun extends ArrayAdapter<String> {  /**   * 记录所有正在下载或等待下载的任务。   */  private Set<BitmapWorkerTask> taskCollection;  /**   * 图片缓存技术的核心类,用于缓存所有下载好的图片,在程序内存达到设定值时会将最少最近使用的图片移除掉。   */  private LruCache<String,Bitmap> mMemoryCache;  /**   * 图片硬盘缓存核心类。   */  private diskLruCache mdiskLruCache;  /**   * GrIDVIEw的实例   */  private GrIDVIEw mPhotoWall;  /**   * 记录每个子项的高度。   */  private int mItemHeight = 0;  public ErJiHuanCun(Context context,int textVIEwResourceID,String[] objects,GrIDVIEw photoWall) {    super(context,textVIEwResourceID,objects);    mPhotoWall = photoWall;    taskCollection = new HashSet<BitmapWorkerTask>();    // 获取应用程序最大可用内存    int maxMemory = (int) Runtime.getRuntime().maxMemory();    int cacheSize = maxMemory / 8;    // 设置图片缓存大小为程序最大可用内存的1/8    mMemoryCache = new LruCache<String,Bitmap>(cacheSize) {      @OverrIDe      protected int sizeOf(String key,Bitmap bitmap) {        return bitmap.getByteCount();      }    };    try {      // 获取图片缓存路径      file cacheDir = getdiskCacheDir(context,"thumb");      if (!cacheDir.exists()) {        cacheDir.mkdirs();      }      // 创建diskLruCache实例,初始化缓存数据      mdiskLruCache = diskLruCache          .open(cacheDir,getAppVersion(context),1,10 * 1024 * 1024);    } catch (IOException e) {      e.printstacktrace();    }  }  @OverrIDe  public VIEw getVIEw(int position,VIEw convertVIEw,VIEwGroup parent) {    final String url = getItem(position);    VIEw vIEw;    if (convertVIEw == null) {      vIEw = LayoutInflater.from(getContext()).inflate(R.layout.photo_layout,null);    } else {      vIEw = convertVIEw;    }    final ImageVIEw imageVIEw = (ImageVIEw) vIEw.findVIEwByID(R.ID.photo);    if (imageVIEw.getLayoutParams().height != mItemHeight) {      imageVIEw.getLayoutParams().height = mItemHeight;    }    // 给ImageVIEw设置一个Tag,保证异步加载图片时不会乱序    imageVIEw.setTag(url);     imageVIEw.setimageResource(R.drawable.ic_launcher);    loadBitmaps(imageVIEw,url);    return vIEw;  }  /**   * 将一张图片存储到LruCache中。   *    * @param key   *      LruCache的键,这里传入图片的URL地址。   * @param bitmap   *      LruCache的键,这里传入从网络上下载的Bitmap对象。   */  public voID addBitmapToMemoryCache(String key,Bitmap bitmap) {    if (getBitmapFromMemoryCache(key) == null) {      mMemoryCache.put(key,bitmap);    }  }  /**   * 从LruCache中获取一张图片,如果不存在就返回null。   *    * @param key   *      LruCache的键,这里传入图片的URL地址。   * @return 对应传入键的Bitmap对象,或者null。   */  public Bitmap getBitmapFromMemoryCache(String key) {    return mMemoryCache.get(key);  }  /**   * 加载Bitmap对象。此方法会在LruCache中检查所有屏幕中可见的ImageVIEw的Bitmap对象,   * 如果发现任何一个ImageVIEw的Bitmap对象不在缓存中,就会开启异步线程去下载图片。   */  public voID loadBitmaps(ImageVIEw imageVIEw,String imageUrl) {    try {      Bitmap bitmap = getBitmapFromMemoryCache(imageUrl);      if (bitmap == null) {        BitmapWorkerTask task = new BitmapWorkerTask();        taskCollection.add(task);        task.execute(imageUrl);      } else {        if (imageVIEw != null && bitmap != null) {          imageVIEw.setimageBitmap(bitmap);        }      }    } catch (Exception e) {      e.printstacktrace();    }  }  /**   * 取消所有正在下载或等待下载的任务。   */  public voID cancelAllTasks() {    if (taskCollection != null) {      for (BitmapWorkerTask task : taskCollection) {        task.cancel(false);      }    }  }  /**   * 根据传入的uniquename获取硬盘缓存的路径地址。   */  public file getdiskCacheDir(Context context,String uniquename) {    String cachePath;    if (Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())        || !Environment.isExternalStorageRemovable()) {      cachePath = context.getExternalCacheDir().getPath();    } else {      cachePath = context.getCacheDir().getPath();    }    return new file(cachePath + file.separator + uniquename);  }  /**   * 获取当前应用程序的版本号。   */  public int getAppVersion(Context context) {    try {      PackageInfo info = context.getPackageManager().getPackageInfo(context.getPackagename(),0);      return info.versionCode;    } catch (nameNotFoundException e) {      e.printstacktrace();    }    return 1;  }  /**   * 设置item子项的高度。   */  public voID setItemHeight(int height) {    if (height == mItemHeight) {      return;    }    mItemHeight = height;    notifyDataSetChanged();  }  /**   * 使用MD5算法对传入的key进行加密并返回。   */  public String hashKeyFordisk(String key) {    String cacheKey;    try {      final MessageDigest mDigest = MessageDigest.getInstance("MD5");      mDigest.update(key.getBytes());      cacheKey = bytesToHexString(mDigest.digest());    } catch (NoSuchAlgorithmException e) {      cacheKey = String.valueOf(key.hashCode());    }    return cacheKey;  }  /**   * 将缓存记录同步到journal文件中。   */  public voID flushCache() {    if (mdiskLruCache != null) {      try {        mdiskLruCache.flush();      } catch (IOException e) {        e.printstacktrace();      }    }  }  private String bytesToHexString(byte[] bytes) {    StringBuilder sb = new StringBuilder();    for (int i = 0; i < bytes.length; i++) {      String hex = Integer.toHexString(0xFF & bytes[i]);      if (hex.length() == 1) {        sb.append('0');      }      sb.append(hex);    }    return sb.toString();  }  /**   * 异步下载图片的任务。   *    *   */  class BitmapWorkerTask extends AsyncTask<String,VoID,Bitmap> {    /**     * 图片的URL地址     */    private String imageUrl;    @OverrIDe    protected Bitmap doInBackground(String... params) {      imageUrl = params[0];      fileDescriptor fileDescriptor = null;      fileinputStream fileinputStream = null;      Snapshot snapShot = null;      try {        // 生成图片URL对应的key        final String key = hashKeyFordisk(imageUrl);        // 查找key对应的缓存        snapShot = mdiskLruCache.get(key);        if (snapShot == null) {          // 如果没有找到对应的缓存,则准备从网络上请求数据,并写入缓存          diskLruCache.Editor editor = mdiskLruCache.edit(key);          if (editor != null) {            OutputStream outputStream = editor.newOutputStream(0);            if (downloadUrlToStream(imageUrl,outputStream)) {              editor.commit();            } else {              editor.abort();            }          }          // 缓存被写入后,再次查找key对应的缓存          snapShot = mdiskLruCache.get(key);        }        if (snapShot != null) {          fileinputStream = (fileinputStream) snapShot.getinputStream(0);          fileDescriptor = fileinputStream.getFD();        }        // 将缓存数据解析成Bitmap对象        Bitmap bitmap = null;        if (fileDescriptor != null) {        // bitmap = BitmapFactory.decodefileDescriptor(fileDescriptor);         WindowManager wm= (WindowManager)getContext().getSystemService(Context.WINDOW_SERVICE);         int wIDth=wm.getDefaultdisplay().getWIDth();         bitmap= ImageResizer.decodeSampleBithmapFromfileDescriptor(fileDescriptor,wIDth/3,wIDth/3);        }        if (bitmap != null) {          // 将Bitmap对象添加到内存缓存当中            addBitmapToMemoryCache(params[0],bitmap);        }        return bitmap;      } catch (IOException e) {        e.printstacktrace();      } finally {        if (fileDescriptor == null && fileinputStream != null) {          try {            fileinputStream.close();          } catch (IOException e) {          }        }      }      return null;    }    @OverrIDe    protected voID onPostExecute(Bitmap bitmap) {      super.onPostExecute(bitmap);      // 根据Tag找到相应的ImageVIEw控件,将下载好的图片显示出来。      ImageVIEw imageVIEw = (ImageVIEw) mPhotoWall.findVIEwWithTag(imageUrl);      if (imageVIEw != null && bitmap != null) {        imageVIEw.setimageBitmap(bitmap);      }      taskCollection.remove(this);    }    /**     * 建立http请求,并获取Bitmap对象。     *      * @param imageUrl     *      图片的URL地址     * @return 解析后的Bitmap对象     */    private boolean downloadUrlToStream(String urlString,OutputStream outputStream) {      httpURLConnection urlConnection = null;      bufferedoutputstream out = null;      BufferedinputStream in = null;      try {        final URL url = new URL(urlString);        urlConnection = (httpURLConnection) url.openConnection();        in = new BufferedinputStream(urlConnection.getinputStream(),8 * 1024);        out = new bufferedoutputstream(outputStream,8 * 1024);        int b;        while ((b = in.read()) != -1) {          out.write(b);        }        return true;      } catch (final IOException e) {        e.printstacktrace();      } finally {        if (urlConnection != null) {          urlConnection.disconnect();        }        try {          if (out != null) {            out.close();          }          if (in != null) {            in.close();          }        } catch (final IOException e) {          e.printstacktrace();        }      }      return false;    }  }}

MainActivity

/** * 照片墙主活动,使用GrIDVIEw展示照片墙。 *  *  */public class MainActivity extends Activity {  /**   * 用于展示照片墙的GrIDVIEw   */  private GrIDVIEw mPhotoWall;  /**   * GrIDVIEw的适配器   */  private ErJiHuanCun mAdapter;  private int mImageThumbSize;  private int mImageThumbSpacing;  @OverrIDe  protected voID onCreate(Bundle savedInstanceState) {    super.onCreate(savedInstanceState);    setContentVIEw(R.layout.activity_main);    //mImageThumbSize = getResources().getDimensionPixelSize(  //     R.dimen.image_thumbnail_size);    //mImageThumbSpacing = getResources().getDimensionPixelSize(  //     R.dimen.image_thumbnail_spacing);    mPhotoWall = (GrIDVIEw) findVIEwByID(R.ID.photo_wall);    mAdapter = new ErJiHuanCun(this,Images.imageThumbUrls,mPhotoWall);    mPhotoWall.setAdapter(mAdapter);/*   mPhotoWall.getVIEwTreeObserver().addOnGlobalLayoutListener(        new VIEwTreeObserver.OnGlobalLayoutListener() {          @OverrIDe          public voID onGlobalLayout() {            final int numColumns = (int) Math.floor(mPhotoWall                .getWIDth()                / (mImageThumbSize + mImageThumbSpacing));            if (numColumns > 0) {              int columnWIDth = (mPhotoWall.getWIDth() / numColumns)                  - mImageThumbSpacing;              mAdapter.setItemHeight(columnWIDth);              mPhotoWall.getVIEwTreeObserver()                  .removeGlobalOnLayoutListener(this);            }          }        });*/  }  @OverrIDe  protected voID onPause() {    super.onPause();    //将缓存记录同步到journal文件中    mAdapter.flushCache();  }  @OverrIDe  protected voID onDestroy() {    super.onDestroy();    // // 退出程序时结束所有的下载任务    mAdapter.cancelAllTasks();  }}
/** * 自定义正方形的ImageVIEw *  */public class MyImageVIEw extends ImageVIEw {  public MyImageVIEw(Context context,AttributeSet attrs,int defStyleAttr) {    super(context,attrs,defStyleAttr);    // Todo auto-generated constructor stub  }  public MyImageVIEw(Context context,AttributeSet attrs) {    super(context,attrs);    // Todo auto-generated constructor stub  }  public MyImageVIEw(Context context) {    super(context);    // Todo auto-generated constructor stub  }  @OverrIDeprotected voID onMeasure(int wIDthMeasureSpec,int heightmeasureSpec) {  // Todo auto-generated method stub    //将高度信息改成宽度即可  super.onMeasure(wIDthMeasureSpec,wIDthMeasureSpec);}}

主Activity的layout

<linearLayout xmlns:androID="http://schemas.androID.com/apk/res/androID"  xmlns:tools="http://schemas.androID.com/tools"  androID:layout_wIDth="match_parent"  androID:layout_height="match_parent"  androID:orIEntation="vertical"  androID:padding="5dp" ><GrIDVIEw  androID:ID="@+ID/photo_wall"  androID:layout_wIDth="match_parent"  androID:layout_height="match_parent"  androID:gravity="center"  androID:horizontalSpacing="5dp"  androID:verticalSpacing="5dp"  androID:numColumns="3"  androID:stretchMode="columnWIDth"  /></linearLayout>

GrIDVIEw中的Item ImageVIEw

<?xml version="1.0" enCoding="utf-8"?><linearLayout xmlns:androID="http://schemas.androID.com/apk/res/androID"  androID:layout_wIDth="match_parent"  androID:layout_height="match_parent"  androID:orIEntation="vertical" ><com.example.imageloader.MyImageVIEw  androID:layout_wIDth="match_parent"  androID:layout_height="0dp"   androID:ID="@+ID/photo"  /></linearLayout>

图片压缩实现

public class ImageResizer { private static final String TAG="ImageResizer"; public static Bitmap decodeSampledBitmapFromresource(Resources res,int resID,int reqWIDth,int reqHeight){   final BitmapFactory.Options options=new BitmapFactory.Options();   options.inJustDecodeBounds=true;   BitmapFactory.decodeResource(res,resID,options);   options.inSampleSize=calculateInSampleSize(options,reqWIDth,reqHeight);   options.inJustDecodeBounds=false;   return BitmapFactory.decodeResource(res,options); } public static Bitmap decodeSampleBithmapFromfileDescriptor(fileDescriptor fd,int reqHeight){   final BitmapFactory.Options options=new BitmapFactory.Options();   options.inJustDecodeBounds=true;   BitmapFactory.decodefileDescriptor(fd,null,reqHeight);   options.inJustDecodeBounds=false;   return BitmapFactory.decodefileDescriptor(fd,options); } public static int calculateInSampleSize(BitmapFactory.Options options,int reqHeight){   if(reqWIDth==0||reqHeight==0)     return 1;   final int wIDth=options.outWIDth;   final int height=options.outHeight;   int inSampleSize=1;   if(height>reqHeight||wIDth>reqWIDth  ){     final int halfheight=height/2;     final int halfWIDth=wIDth/2;     //尽最大限度的压缩图片,不能让图片的宽高比ImageVIEw的宽高小,否则在将     //图片显示到ImageVIEw时,图片会放大导致图片失真   while(halfheight/inSampleSize>reqHeight&&halfWIDth/inSampleSize>reqWIDth){      inSampleSize*=2;    }   }   return inSampleSize; }}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持编程小技巧。

总结

以上是内存溢出为你收集整理的Android二级缓存加载图片实现照片墙功能全部内容,希望文章能够帮你解决Android二级缓存加载图片实现照片墙功能所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/web/1145695.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-31
下一篇 2022-05-31

发表评论

登录后才能评论

评论列表(0条)

保存