获取方式

1.内存

内存缓存主要使用LRU缓存算法,引用support-v4中的LruCache,
通过键值对的形式获取到相应的bitmap,配置如下:

      //初始化缓存策略int maxMem = (int) (Runtime.getRuntime().maxMemory() / 1024);int cacheSize = maxMem / 8;mMemCache = new LruCache<String, Bitmap>(cacheSize) {@Overrideprotected int sizeOf(String key, Bitmap value) {//计算缓存对象大小return value.getRowBytes() * value.getHeight() / 1024;}};

2.磁盘缓存

磁盘缓存也是采用LRU缓存算法,一般从网上直接获取DiskLruCache源码,配置好,通过键值对的形式获取。
DiskLruCache的入口函数如下:

 /**  执行初始化磁盘缓存操作,*  注意directory要先mkdir*/public static DiskLruCache open(File directory, int appVersion, int valueCount, long maxSize);/*** 获取磁盘缓存路径* @param context* @param uniqueName* @return */public static File getDiskCacheDir(Context context, String uniqueName) {// Check if media is mounted or storage is built-in, if so, try and use external cache dir// otherwise use internal cache dirfinal String cachePath =Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState()) ||!isExternalStorageRemovable() ? getExternalCacheDir(context).getPath() :context.getCacheDir().getPath();return new File(cachePath + File.separator + uniqueName);}

directory:为缓存存储路径,
appVersion: 版本号,改变后缓存会改变,一般设为1
valueCount: 单节点对应数据个数,一般为1
maxSize: 最大缓存容量,快满会自动清理,单位为Byte

注意的是这里的key值不能直接存图片url,而是需要将其转化为md5值,避免特殊字符干扰。


3.磁盘I/O

通过ContentResolver直接遍历获取磁盘上的图片即可。

//获取图片存储路径
Uri mImageUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
ContentResolver mContentResolver = getContentResolver();
//获得游标并执行相关数据库表的查询
Cursor mCursor = mContentResolver.query(mImageUri,null,                   MediaStore.Images.Media.MIME_TYPE + "=? or "+                       MediaStore.Images.Media.MIME_TYPE +"=?",new String[]{                              "image/jpeg","image/png"},                      MediaStore.Images.Media.DATE_MODIFIED);
if(mCursor==null){return;
}
while(mCursor.moveToNext()){//获取图片的路径
String path = mCursor.getString(mCursor.getColumnIndex(MediaStore.Images.Media.DATA));//TODO 储存path
}

4.网络

直接通过HttpURLConnection获取到IO流便可

                //网络直接获取到stream,注意getInputStream操作才执行网络请求HttpURLConnection connect = null;InputStream in = null;try {final URL urlString = new URL(url);connect = (HttpURLConnection) urlString.openConnection();connect.setDoInput(true);connect.connect();in = connect.getInputStream();}...

使用事项

1.bitmap占用内存过大问题

android里bitmap是个大胖子,加载大量图片时需要对其进行缩放处理,而加载单张全图时,则注意将对应的imageView设置为弱引用,这样gc会更快回收。
bitmap缩放使用以下方法:

      /*** 根据文件描述符来传入图片流并压缩成制定的bitmap* @param fd* @param reqWidth* @param reqHeight* @return*/public static Bitmap decodeByFD(FileDescriptor fd, int reqWidth, int reqHeight) {BitmapFactory.Options options  = new BitmapFactory.Options();//为true时是只取样,几乎不占内存options.inJustDecodeBounds = true;BitmapFactory.decodeFileDescriptor(fd,null,options);options.inSampleSize = calculateInSampleSize(options,reqWidth,reqHeight);options.inJustDecodeBounds = false;return BitmapFactory.decodeFileDescriptor(fd,null,options);}/*** 计算压缩比,一般是2的倍数,为1时保留原来的格式* @param options* @param reqWidth* @param reqHeight* @return*/private static int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) {if (reqWidth == 0 && reqHeight == 0) {return 1;}int realWidth = options.outWidth;int realHeight = options.outHeight;int inSampleSize = 1;if (reqWidth < realWidth || reqHeight < realHeight) {realWidth /= 2;realHeight /= 2;while((realWidth/inSampleSize)>=reqHeight&&(realHeight/inSampleSize)>=reqWidth){inSampleSize*=2;}//这里是考虑到极端情况,宽度比高度大很多的图片需要继续缩放//总的图片大小long totalPixels = realWidth * realHeight / inSampleSize;//imageView提供的大小final long totalReqPixelsCap = reqWidth * reqHeight * 2;while (totalPixels > totalReqPixelsCap) {inSampleSize *= 2;totalPixels /= 2;}}return inSampleSize;}

不一定是decodeByFile,可以利用BitmapFactory提供的其他decode方法,但注意的是,使用decodeStream时,两次操作会改变fileInputStream的位置信息,使得第二次decode获取到的为null,根本原因是fileInputStream为有序的。

另外MedioStore.Images.Thumbnails中提供了本地图片缩略图的获取方式,如下:

                String[] projection = new String[]{MediaStore.Images.Media._ID, MediaStore.Images.Media.DATA};String[] condition = new String[]{url};Cursor cursor = mContext.getContentResolver().query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, projection, MediaStore.Images.Media.DATA + " =? ",condition, null);if (cursor == null) {return;}if (cursor.moveToNext()) {long imageId = cursor.getLong(cursor.getColumnIndex(MediaStore.Images.Media._ID));String data = cursor.getString(cursor.getColumnIndex(MediaStore.Images.Media.DATA));bitmap = MediaStore.Images.Thumbnails.getThumbnail(mContext.getContentResolver(), imageId,MediaStore.Images.Thumbnails.MICRO_KIND, null);}

getThumbnail可以获取到本地图片的缩略图,且缩略图有两种,分别是MINI_KIND 512 x 384和MICRO_KIND 96 x 96 此方法与bitmapFactory的decode的效率还有待深入比较。
另外,这里有个小bug,就是使用getContentResolver查找不到MICRO_KIND类型图片的路径,MINI_KIND是可以获取的,欢迎有兴趣的朋友一起讨论。


2线程安全问题

大量的图片操作伴随高耗时,所以除了内存缓存中的获取,一般采用线程池来异步加载图片,保证不阻碍UI主线程。
而ImageView的setBitmap操作要在主线程中操作,所以完成图片处理需要及时把图片信息通过主线程的handler传递message出去。

通过AsyncTask的executeOnExecutor方法可以自己配置并发使用的线程池,AsyncTask自带的线程池是串行的。


3界面卡顿问题

1)listview和gridview滑动过快,导致频繁的图片加载
2)listview和gridview的imageView控件复用,导致bitmap在未被加载完全时,显示被复用的bitmap

解决方案:
1 ) 监听滑动状态,通过OnScrollStateChanged监听滑动操作,如果使快速滑动时,不执行i/o和网络请求,代码如下:

        mGridView.setOnScrollListener(new AbsListView.OnScrollListener() {@Overridepublic void onScrollStateChanged(AbsListView view, int scrollState) {if (scrollState == AbsListView.OnScrollListener.SCROLL_STATE_IDLE) {mPhotoAdapter.setmIsScroll(false);mPhotoAdapter.notifyDataSetChanged();} else {mPhotoAdapter.setmIsScroll(true);}}});

2) getView中对imageView的bitmap的url进行记录,即设置完bitmap后,将图片的url通过imageView.setTag保存起来,在getView开始时就用实际的url与getTag里对比,如果不一致,则设置bitmap为默认图像,避免图片错位。

android图片获取加载小结相关推荐

  1. Android 图片异步加载的体会,SoftReference已经不再适用

    在网络上搜索Android图片异步加载的相关文章,目前大部分提到的解决方案,都是采用Map<String, SoftReference<Drawable>>  这样软引用的方式 ...

  2. android图片异步加载图片,Android 异步加载图片分析总结

    研究了android从网络上异步加载图像,现总结如下: (1)由于android UI更新支持单一线程原则,所以从网络上取数据并更新到界面上,为了不阻塞主线程首先可能会想到以下方法. 在主线程中new ...

  3. Android图片的加载与压缩

    目录 图片加载 图片压缩 Bitmap(位图)的压缩 色位深度 图片文件与Bitmap 压缩--位图读取 压缩--位图写入 对compress的使用反思 注意事项 图片加载 在了解图片压缩前,先简单介 ...

  4. Android 图片异步加载

    所谓图片异步加载,意思是不用一次把图片全部加载完,你可以叫它延迟加载,缓冲加载都行. 看看你有没有这种需求:某篇文章图片很多,如果在载入文章时就载入所有图片,无疑会延缓载入速度,让用户等更久,所以,我 ...

  5. android图片异步加载解决步骤

    Android – Asynchronous image loading in ListView Problem: How to load images in ListView asynchronou ...

  6. android复位机器人图片_Universal-Image-Loader 图片异步加载类库还不熟?

    码个蛋(codeegg) 第 824 次推文 作者:欢醉 博客:https://cloud.tencent.com/developer/article/1026386 码妞看世界 写在前面 这个图片异 ...

  7. Android 自定义ImageView加载图片

    自定义imageview功能: 可以实现设置图片显示的时候,依据本身的比例进行图片的缩放 加载图片效果: 使用ImageLoader来加载 图片: 首先将ImageLoader的jar包关联到项目中 ...

  8. android 实现异步加载图片,Android中ImageView异步加载图片类

    本源码是从网络找到经修改以方便直接调用感觉用着还可以 首先在项目中添加一个专门加载图片的类AsyncImageLoaderpackage com.demo.core; import java.io.I ...

  9. android webview 图片异步加载,Webview 图片异步加载及bug解决

    在项目中新闻显示需要使用图片的异步加载,并且在加载图片前和加载图片失败时显示默认图片. 关于webview中图片的异步加载的思路如下: 方案一:由前端同学全权负责(使用js实现异步加载) 方案二:an ...

最新文章

  1. Colab不好用,有人花两年开发了一个新notebook,支持实时协作还更快
  2. Tensorflow Lite 编译
  3. mysql数据库模型生成表_PowerDesigner逆向生成MYSQL数据库表结构总结
  4. FastReport.net 使用记录
  5. linux mysql 实战_linux实用实战
  6. linux上源码安装mysql,Linux中源码包安装MySQL的shell脚本
  7. Python学习之解释器的简单使用
  8. 【工程项目经验】dmesg查看linux系统缓存日志
  9. 剑指offer面试题17. 打印从1到最大的n位数
  10. HDU1754 I Hate It (线段树单点修改+区间查询)
  11. Codeforces 758F Geometrical Progression
  12. keras 多分类一些函数参数设置
  13. SharePoint 2013 开发——开发并部署Provider-hosted APP
  14. word 方框内打勾√或打叉×
  15. 08s01 mysql_Mysql:SQL 错误 [08S01]: Communications link failure
  16. 手把手教你做短视频去水印微信小程序(2-首页)
  17. 炒股配资的杠杆是几倍?
  18. 错误 C2679 二进制“=”: 没有找到接受“const _Ty”类型的右操作数的运算符(或没有可接受的转换)的一种情况发生的错误
  19. 推荐算法的多模型融合
  20. 拆解报告:爱否开物1A2C 65W PD氮化镓充电器智融SW3516十分表现抢眼

热门文章

  1. 用来代替本机IP的万能IP:127.0.0.1
  2. python3.9下载_Python-3.9下载_Python下载_Python最新版_5分享
  3. Java选择题(三十)
  4. android Java开发设计模式及在android中的应用解析
  5. oracle 创建nchar类型,Oracle NChar类型
  6. 均方根误差,平均绝对误差与标准差
  7. hrms系统的服务器名是什么,解读HRMS.doc
  8. java-php-net-python-动漫产品销售计算机毕业设计程序
  9. 如何从0到1做一次完整的安全测试
  10. java实现敏感词过滤算法DFA并忽略敏感词中的特殊字符