android 网络加载图片,对图片资源进行优化,并且实现内存双缓存 + 磁盘缓存

经常会用到 网络文件 比如查看大图片数据 资源优化的问题,当然用开源的项目  Android-Universal-Image-Loader  或者 ignition 都是个很好的选择。

在这里把原来 写过的优化的代码直接拿出来,经过测试千张图片效果还是不错的。

免费培训课:http://www.jinhusns.com/Products/Curriculum/?type=xcj

工程目录

至于 Activity 就是加载了 1个网格布局

01./**

02.*   实现 异步加载 和   2级缓存

03.*/

04.public class ImagedownActivity extends Activity {

05.

06.public static String filepath;

07.@Override

08.public void onCreate(Bundle savedInstanceState) {

09.super.onCreate(savedInstanceState);

10.setContentView(R.layout.main);

11.filepath =   this.getCacheDir().getAbsolutePath();

12.GridView gv=(GridView)findViewById(R.id.gridview01);

13.//设置列数

14.gv.setNumColumns(3);

15.//配置适配器

16.gv.setAdapter(new Myadapter(this));

17.}

18.

19.@Override

20.protected void onDestroy() {

21.// TODO Auto-generated method stub

22.//activity 销毁时,清除缓存

23.MyImageLoader.removeCache(filepath);

24.super.onDestroy();

25.}

26.

27.}

接下来 Myadapter.java(给网格每个item塞入图片 )在生成每个 item 异步请求网络获取image

01.public class Myadapter extends BaseAdapter {

02.private Context context;

03.private String  root ="http://192.168.0.100:8080/Android_list/";

04.private String[] URLS;

05.private final MyImageLoader  myImageLoader = new MyImageLoader(context);;

06.

07./**

08.* adapter 初始化的时候早一堆数据

09.* 这里我请求的是自己搭的服务器

10.* @param context

11.*/

12.public  Myadapter(Context context){

13.this.context =context;

14.URLS = new String[999];

15.for (int i = 0; i < 999; i++) {

16.URLS[i] = root + (i+1)+".jpg";

17.}  

18.}

19.

20.

21.@Override

22.public int getCount() {

23.return URLS.length;

24.}

25.

26.@Override

27.public Object getItem(int position) {

28.return URLS[position];

29.}

30.

31.@Override

32.public long getItemId(int position) {

33.return URLS[position].hashCode();

34.}

35.

36.

37.

38.@Override

39.public View getView(int position, View view, ViewGroup parent) {

40.ImageView imageView;

41.if(view==null){

42.imageView=new ImageView(context);

43.imageView.setLayoutParams(new GridView.LayoutParams(200,190));

44.imageView.setAdjustViewBounds(false);

45.imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);

46.imageView.setPadding(5, 5, 5, 5);

47.}else{

48.imageView=(ImageView)view;

49.}

50.myImageLoader.downLoad(URLS[position], (ImageView)imageView , context);

51.return imageView;

52.}

53.}

MyImageLoader.java

001.public class MyImageLoader { 

002.

003.//最大内存 

004.final static int memClass = (int) Runtime.getRuntime().maxMemory();   

005.private Context context; 

006.

007.// 是否缓存到硬盘 

008.private boolean  diskcache = true

009.

010.// 定义一级 缓存的图片数 

011.private static final int catch_num = 10

012.

013.// 定义二级缓存 容器  软引用 

014.private static ConcurrentHashMap<String, SoftReference<Bitmap>> current_hashmap = new ConcurrentHashMap<String, SoftReference<Bitmap>>(); 

015.

016.// 定义一级缓存容器  强引用       (catch_num ,0.75f,true) 默认参 数                                                                                                                        2.加载因子默认        3.排序模式 true 

017.private static LinkedHashMap<String, Bitmap> link_hashmap = new LinkedHashMap<String, Bitmap>(catch_num ,0.75f,true) { 

018.

019.// 必须实现的方法 

020.protected boolean removeEldestEntry(java.util.Map.Entry<String, Bitmap> eldest) { 

021./** 当一级缓存中 图片数量大于 定义的数量 放入二级缓存中

022.*/

023.if (this.size() > catch_num) { 

024.// 软连接的方法 存进二级缓存中 

025.current_hashmap.put(eldest.getKey(), new SoftReference<Bitmap>( 

026.eldest.getValue())); 

027.//缓存到本地 

028.cancheToDisk(eldest.getKey(),eldest.getValue() ); 

029.

030.return true

031.

032.return false

033.}; 

034.}; 

035.

036.public MyImageLoader(Context context) { 

037.

038.

039.

040.

041./**   

042.*  外部调用此方法   进行下载图片  

043.*/

044.public void downLoad(String key , ImageView imageView,Context context){ 

045.// 先从缓存中找   。   

046.context = this.context; 

047.

048.Bitmap bitmap = getBitmapFromCache(key); 

049.if( null!= bitmap){  

050.imageView.setImageBitmap(bitmap); 

051.cancleDownload(key, imageView);         //取消下载 

052.return

053.}     

054.

055.// 缓存中 没有  把当前的 imageView 给他 得到 task  

056.if(cancleDownload(key, imageView)){     //没有任务进行。,。。开始下载 

057.ImageDownloadTask task = new ImageDownloadTask(imageView); 

058.Zhanwei_Image  zhanwei_image = new Zhanwei_Image(task); 

059.//先把占位的图片放进去 

060.imageView.setImageDrawable(zhanwei_image); 

061.// task执行任务 

062.task.execute(key);  

063.

064.

065.

066.

067./** 此方法 用于优化  : 用户直接 翻到 哪个 就先加载 哪个、

068.* @param key                - URL

069.* @param imageView          - imageView

070.*  core: 给当前的 imageView 得到给他下载的 task

071.*/

072.

073.private boolean cancleDownload(String key,ImageView imageView){ 

074.// 给当前的 imageView 得到给他下载的 task 

075.ImageDownloadTask task = getImageDownloadTask(imageView); 

076.if(null != task){ 

077.String down_key = task.key; 

078.if( null == down_key || !down_key.equals(key)){ 

079.task.cancel(true);        // imageview 和 url 的key不一样       取消下载    

080.}else

081.return false;      //正在下载:  

082.}   

083.

084.return true;            //没有正在下载 

085.

086.

087.

088.

089.//  public void getThisProcessMemeryInfo() { 

090.//        int pid = android.os.Process.myPid(); 

091.//        android.os.Debug.MemoryInfo[] memoryInfoArray = activityManager.getProcessMemoryInfo(new int[] {pid}); 

092.//        System.out.println("本应用当前使用了" + (float)memoryInfoArray[0].getTotalPrivateDirty() / 1024 + "mb的内存"); 

093.//    } 

094.

095.

096.

097./**

098.* 从缓存中得到 图片的方法 1.先从一级 缓存找 linkhashmap 不是线程安全的 必须要加同步

099.*/

100.public Bitmap getBitmapFromCache(String key) { 

101.//1.先在一级缓存中找 

102.synchronized (link_hashmap) { 

103.Bitmap bitmap = link_hashmap.get(key); 

104.if (null != bitmap) { 

105.link_hashmap.remove(key); 

106.// 按照 LRU是Least Recently Used 近期最少使用算法 内存算法 就近 就 原则 放到首位 

107.link_hashmap.put(key, bitmap); 

108.System.out.println(" 在缓存1中找图片了 =" +key); 

109.return bitmap; 

110.

111.

112.

113.// 2. 到二级 缓存找 

114.SoftReference<Bitmap> soft = current_hashmap.get(key); 

115.if (soft != null) { 

116.//得到 软连接 中的图片 

117.Bitmap soft_bitmap = soft.get();       

118.if (null != soft_bitmap) { 

119.System.out.println(" 在缓存2中找图片了 =" +key); 

120.return soft_bitmap; 

121.

122.} else

123.// 没有图片的话 把这个key删除 

124.current_hashmap.remove(key);       

125.

126.

127.

128.//3.都没有的话去从外部缓存文件读取 

129.if(diskcache){ 

130.Bitmap bitmap = getBitmapFromFile(key); 

131.if(bitmap!= null){ 

132.link_hashmap.put(key, bitmap);   //将图片放到一级缓存首位 

133.return bitmap; 

134.

135.

136.

137.return null

138.

139.

140.

141./**

142.* 缓存到本地文件

143.* @param key

144.* @param bitmap

145.*/

146.public static void cancheToDisk(String key ,Bitmap bitmap ){ 

147.//2.缓存bitmap至/data/data/packageName/cache/文件夹中 

148.try

149.String fileName = getMD5Str(key); 

150.String filePath = ImagedownActivity.filepath + "/" + fileName; 

151.System.out.println("缓存到本地===" + filePath); 

152.FileOutputStream fos = new FileOutputStream(filePath); 

153.bitmap.compress(Bitmap.CompressFormat.JPEG, 100, fos); 

154.

155.} catch (Exception e) { 

156.

157.

158.

159.

160.

161./**

162.* 从外部文件缓存中获取bitmap

163.* @param url

164.* @return

165.*/

166.private Bitmap getBitmapFromFile(String url){ 

167.Bitmap bitmap = null

168.String fileName = getMD5Str(url); 

169.if(fileName == null){ 

170.return null

171.}    

172.String filePath = ImagedownActivity.filepath + "/" + fileName;       

173.try

174.FileInputStream fis = new FileInputStream(filePath); 

175.bitmap = BitmapFactory.decodeStream(fis); 

176.System.out.println("在本地缓存中找到图片==="+ filePath); 

177.} catch (FileNotFoundException e) { 

178.System.out.println("getBitmapFromFile==="+ e.toString()); 

179.e.printStackTrace(); 

180.bitmap = null

181.

182.return bitmap; 

183.

184.

185.

186.

187./**

188.* 清理文件缓存

189.* @param dirPath

190.* @return

191.*/

192.public static boolean removeCache(String dirPath) { 

193.File dir = new File(dirPath); 

194.File[] files = dir.listFiles(); 

195.if(files == null || files.length == 0) { 

196.return true

197.

198.int dirSize = 0

199.//这里删除所有的缓存 

200.int all_ = (int) ( 1 * files.length + 1); 

201.//对files 进行排序 

202.Arrays.sort(files, new FileLastModifiedSort()); 

203.for (int i = 0; i < all_ ; i++) { 

204.files[i].delete(); 

205.

206.return true

207.

208.

209.

210./**

211.* 根据文件最后修改时间进行排序

212.*/

213.private static class FileLastModifiedSort implements Comparator<File> { 

214.@Override

215.public int compare(File lhs, File rhs) { 

216.if(lhs.lastModified() > rhs.lastModified()) { 

217.return 1

218.} else if(lhs.lastModified() == rhs.lastModified()) { 

219.return 0

220.} else

221.return -1

222.

223.

224.

225.

226.

227./**  

228.* MD5 加密  

229.*/

230.private static String getMD5Str(String str) {    

231.MessageDigest messageDigest = null;    

232.try {    

233.messageDigest = MessageDigest.getInstance("MD5");    

234.messageDigest.reset();    

235.messageDigest.update(str.getBytes("UTF-8"));    

236.} catch (NoSuchAlgorithmException e) {    

237.System.out.println("NoSuchAlgorithmException caught!");    

238.return null

239.} catch (UnsupportedEncodingException e) {    

240.e.printStackTrace(); 

241.return null

242.}    

243.

244.byte[] byteArray = messageDigest.digest();    

245.StringBuffer md5StrBuff = new StringBuffer();    

246.for (int i = 0; i < byteArray.length; i++) {                

247.if (Integer.toHexString(0xFF & byteArray[i]).length() == 1)    

248.md5StrBuff.append("0").append(Integer.toHexString(0xFF & byteArray[i]));    

249.else

250.md5StrBuff.append(Integer.toHexString(0xFF & byteArray[i]));    

251.}    

252.return md5StrBuff.toString();    

253.}   

254.

255.

256.// ------------------------ 异步加载---------------------------- 

257./**

258.*  占位的 图片 或者 颜色      用来绑定 相应的图片

259.*/

260.class Zhanwei_Image extends ColorDrawable{ 

261.//里面存放 相应 的异步 处理时加载好的图片 ----- 相应的 task 

262.private final WeakReference<ImageDownloadTask>  taskReference; 

263.public Zhanwei_Image(ImageDownloadTask task){    

264.super(Color.BLUE); 

265.taskReference = new WeakReference<MyImageLoader.ImageDownloadTask>(task);  

266.}   

267.// 返回去这个 task 用于比较 

268.public ImageDownloadTask getImageDownloadTask(){ 

269.return taskReference.get(); 

270.

271.

272.

273.

274.// 根据 给 的 iamgeView、 得到里面的 task  用于和当前的 task比较是不是同1个 

275.private ImageDownloadTask getImageDownloadTask(ImageView imageView){ 

276.if( null != imageView){ 

277.Drawable drawable = imageView.getDrawable();     

278.if( drawable instanceof Zhanwei_Image) 

279.return ((Zhanwei_Image)drawable).getImageDownloadTask(); 

280.

281.

282.return null

283.

284.

285.

286.

287./**

288.* 把图片 添加到缓存中

289.*/

290.public void addBitmap(String key, Bitmap bitmap) { 

291.if (null != bitmap) { 

292.synchronized (link_hashmap) {         // 添加到一级 缓存中 

293.link_hashmap.put(key, bitmap); 

294.

295.

296.

297.

298.

299./** 在后台 加载每个图片

300.*  第一个参数 第2个要进度条不 第三个返回结果 bitmap

301.*/

302.class ImageDownloadTask extends AsyncTask<String, Void, Bitmap> { 

303.

304.private String key; 

305.private WeakReference<ImageView> imgViReference; 

306.

307.public ImageDownloadTask(ImageView imageView) { 

308.//imageView 传进来 。。要给哪个iamgeView加载图片 

309.imgViReference = new WeakReference<ImageView>( 

310.imageView); 

311.

312.

313.@Override

314.protected Bitmap doInBackground(String... params){ 

315.key = params[0]; 

316.//调用下载函数 根据 url 下载       

317.return downloadBitmap(key); 

318.

319.

320.@Override

321.protected void onPostExecute(Bitmap result) { 

322.if(isCancelled()){ 

323.result = null

324.

325.

326.System.out.println("result=="+ result.getByteCount()+"---memClassmemery="+memClass); 

327.

328.if(null!= result){ 

329.//保存到缓存中 

330.addBitmap(key, result); 

331.ImageView  imageView = imgViReference.get(); 

332.if( null != imageView){   

333.//向 imageView 里面放入 bitmap          

334.ImageDownloadTask task = getImageDownloadTask(imageView); 

335.

336./**

337.*  判断 是不是 同一个 task( )

338.*  如果当前这个 task  ==  imageView 里面的那个 task 就是同1个

339.*/

340.if( this == task ){ 

341.imageView.setImageBitmap(result); 

342.

343.

344.

345.

346.

347.

348.

349.

350./**

351.* 连接网络 客户端 下载图片

352.*/

353.private Bitmap downloadBitmap(String url) { 

354.

355.final HttpClient client = AndroidHttpClient.newInstance("Android"); 

356.final HttpGet getRequest = new HttpGet(url);  

357.try

358.HttpResponse response = client.execute(getRequest); 

359.final int statusCode = response.getStatusLine().getStatusCode(); 

360.

361.if (statusCode != HttpStatus.SC_OK) { 

362.

363.Log.w("ImageDownloader", "Error " + statusCode + " while retrieving bitmap from " + url); 

364.return null

365.

366.

367.final HttpEntity entity = response.getEntity(); 

368.if (entity != null) { 

369.InputStream inputStream = null

370.try

371.

372.inputStream = entity.getContent();                  

373./**

374.*  1.没有压缩直接将生成的bitmap返回去

375.*/

376.//                  return BitmapFactory.decodeStream(inputStream); 

377.

378./**

379.*  2.得到data后在这里把图片进行压缩

380.*/

381.byte[] data = StreamTool.read(inputStream);  

382.return  BitmapManager.scaleBitmap(context, data, 0.3f); 

383.//                   return BitmapFactory.decodeStream(new FlushedInputStream(inputStream)); 

384.} finally

385.if (inputStream != null) { 

386.inputStream.close(); 

387.

388.entity.consumeContent(); 

389.

390.

391.} catch (IOException e) { 

392.getRequest.abort(); 

393.} catch (IllegalStateException e) { 

394.getRequest.abort(); 

395.} catch (Exception e) { 

396.getRequest.abort(); 

397.} finally

398.if ((client instanceof AndroidHttpClient)) { 

399.((AndroidHttpClient) client).close(); 

400.

401.

402.return null

403.

404.

405.}

StreamTool.java

01.public class StreamTool { 

02.

03.public static  byte[] read(InputStream in) throws Exception{ 

04.ByteArrayOutputStream  out_byte = new ByteArrayOutputStream(); 

05.byte[] buff = new byte[1024]; 

06.int len=0

07.while((len = in.read(buff))!= -1){ 

08.//写到内存中  字节流 

09.out_byte.write( buff, 0 , len); 

10.}    

11.out_byte.close();    

12.// 把内存数据返回 

13.return  out_byte.toByteArray();  

14.

15.}

BitmapManager.java ( 这个类里面对 网络资源的图片 进行了优化)

001.public class BitmapManager {

002.

003./**

004.* 按屏幕适配Bitmap

005.*/

006.public static Bitmap scaleBitmap(Context context, byte[] data , float percent) {

007.

008.//这里我不获取了,假设是下面这个分辨率

009.int screenWidth =   540;

010.int screenrHeight = 950;

011.//设置 options

012.BitmapFactory.Options options = new BitmapFactory.Options();

013./**

014.*  BitmapFactory.Options这个类,有一个字段叫做 inJustDecodeBounds.SDK中对这个成员的说明是这样的:

015.*  If set to true, the decoder will return null (no bitmap), but the out…

016.*  也就是说,如果我们把它设为true,那么BitmapFactory.decodeFile(String path, Options opt)并不会真的返回一个Bitmap给你,

017.*  它仅仅会把它的宽,高取回来给你,这样就不会占用太多的内存,也就不会那么频繁的发生OOM了。

018.*/

019.options.inJustDecodeBounds = true;

020.

021.//读取

022.Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length, options);

023.

024.int imgWidth = options.outWidth;

025.int imgHeight = options.outHeight;

026.

027.//如果比你设置的宽高大  就进行缩放,

028.if(imgWidth > screenWidth * percent || imgHeight > screenrHeight * percent) {

029.options.inSampleSize = calculateInSampleSize(options, screenWidth, screenrHeight, percent);

030.}

031.

032.

033./**

034.* If set to true, the decoder will return null (no bitmap), but the out... fields will still be set, allowing the caller

035.* to query the bitmap without having to allocate the memory for its pixels.

036.*

037.* 如果设置成 true,这个编码将会返回1个null , 但是那个区域仍将被设置(也就是存在),允许(调用者)去查询那个没有分配 内存的像素  bitmap

038.*/

039.options.inJustDecodeBounds = false;

040.

041./**

042.*  Android的Bitmap.Config给出了bitmap的一个像素所对应的存储方式,

043.*  有RGB_565,ARGB_8888,ARGB_4444,ALPHA_8四种。RGB_565表示的是红绿蓝三色分别用5,6,5个比特来存储,

044.*  一个像素占用了5+6+5=16个比特。ARGB_8888表示红绿蓝和半透明分别用8,8,8,8个比特来存储,

045.*  一个像素占用了8+8+8+8=32个比特。这样的话如果图片是以RGB_8888读入的,那么占用内存的大小将是RGB_565读入方式的2倍。

046.*  通常我们给Imagview加载图片是通过setDrawable或者在xml文件中用android:src来设置

047.*  默认的加载图片大小的方式是以RGB_8888读入的。

048.*

049.*/

050.options.inPreferredConfig = Bitmap.Config.RGB_565;

051.

052./**

053.* If this is set to true, then the resulting bitmap will allocate its pixels such that they can be purged

054.* if the system needs to reclaim memory.

055.*

056.* 如果设置成 true, 这个结果bitmap 将会被分配像素,这样他们就能被 系统回收了,当系统需要回收内存的时候

057.*/

058.options.inPurgeable = true;

059.

060./**

061.* This field works in conjuction with inPurgeable.

062.* 这个方法是在   inPurgeable 的基础上工作的

063.*/

064.options.inInputShareable = true;

065.

066.

067.bitmap = BitmapFactory.decodeByteArray(data, 0, data.length, options);

068.

069.System.out.println("data==="+  data.length +"  change == bitmap byte "+ bitmap.getByteCount());

070.return bitmap;

071.}

072.

073.

074.

075.//                                                    options       reqWidth 屏幕宽      reqHeight屏幕高      你的view是屏幕的多大

076.public static int calculateInSampleSize(BitmapFactory.Options options, int screenWidth, int screenHeight ,float percent) {

077.

078.// 原始图片宽高

079.final int height = options.outHeight;

080.final int width = options.outWidth;

081.// 倍数

082.int inSampleSize = 1;

083.

084.if (height > screenHeight * percent || width > screenWidth * percent) {

085.

086.// 计算目标宽高与原始宽高的比值

087.final int inSampleSize_h = Math.round((float) height / (float)( screenHeight * percent));

088.

089.final int inSampleSize_w = Math.round((float) width / (float)( screenWidth * percent));

090.

091.// 选择两个比值中较小的作为inSampleSize的

092.inSampleSize = inSampleSize_h < inSampleSize_w ? inSampleSize_h : inSampleSize_w;

093.

094.System.out.println("inSampleSize===="+ inSampleSize);

095.//

096.if(inSampleSize < 1) {

097.inSampleSize = 1;

098.}

099.}

100.//简单说这个数字就是 缩小为原来的几倍,根据你的image需要占屏幕多大动态算的(比如你用的权重设置layout)

101.return inSampleSize;

102.}

103.}

这个是代码输出的最多给这个进程分配的内存 128M

可以看到我上面的bitmapManager 里面有个   options.inPreferredConfig   注释写的很清楚,可以上去看一下,接下来贴几种格式的效果图

rgb565  和  argb_444  所占的内存              (54000)

看一下 argb_8888                    (  108000)

当然可能仔细看的人会看到我一开始截的 鸣人的效果图 上半部分 和 下半部分的颜色会有点问题。上面的rgb_565 生成的,和原图色彩可能会有点出入。

但是内存真心少了一半,所以各种取舍就看个人了,代码注释都谢的很清楚了。

至于 : MyImageLoaderLru.java  其实就是    MyImageLoader.java

先贴出代码不同地方的代码 : 就是在强引用的地方  把  LinkedHashMap 换成了 LruCache

01.// 获取单个进程可用内存的最大值 

02.// 方式一:使用ActivityManager服务(计量单位为M) 

03./*int memClass = ((ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE)).getMemoryClass();*/

04.// 方式二:使用Runtime类(计量单位为Byte) 

05.final static int memClass = (int) Runtime.getRuntime().maxMemory(); 

06.// 3. 定义一级缓存容器  强引用       (catch_num /2,0.75f,true) 默认参 数                                                                                                                        2.加载因子默认        3.排序模式 true

07.final static int  max = memClass/5;

08.

09.// LruCache 用强引用将  图片放入     LinkedHashMap

10.private static LruCache<String, Bitmap> lrucache = new LruCache<String, Bitmap>(max) {

11.protected int sizeOf(String key, Bitmap value) { 

12.if(value != null) { 

13.// 计算存储bitmap所占用的字节数 

14.return value.getRowBytes() * value.getHeight(); 

15.} else

16.return 0

17.

18.

19.

20.@Override

21.protected void entryRemoved(boolean evicted, String key, Bitmap oldValue, Bitmap newValue) { 

22.if(oldValue != null) { 

23.// 当硬引用缓存容量已满时,会使用LRU算法将最近没有被使用的图片转入软引用缓存 

24.current_hashmap.put(key, new SoftReference<Bitmap>(oldValue)); 

25.

26.

27.};

1. 强引用:LruCache 后面再说,其实他内的内部封装的就是1个 LinkedHashMap 。LinkedHashMap 是线程不安全的,所以上面都会用到同步。

2. 软引用:ConcurrentHashMap 是线程安全的,并且支持高并发很有效率,这个后面也会说到,为什么要用 软引用 SoftReference,这个是在系统将要oom时,就会回收

软引用的对象资源,所以才会用到他,防止程序出异常 。

3. 磁盘缓存: 这个经常会看到网易新闻等,应用有些界面你看了很多图片,往上翻很多, 其实没有再次访问网络,会将部分image缓存在sdcard里。

4. 其中1个优化: 当比如用户快速滑动到 最底部,其实是最先加载显示给用户的部分的内容的,这样就是用户看到哪加载哪,1个是快,1个是避免资源浪费。

原理: 当用户进入界面加载图片 ,首先会从1级缓存强引用中找,找不到回去2级缓存软引用中找,找不到再去sdcard中找,再找不到才会去请求网络加载资源。

当然sdcard的缓存 看个人需求是否需要。

注: android 4.0 后 对 SoftReference 的回收机制进行了改变,所以你是可以不用 2级缓存的,直接去掉就好了。

只要控制好你的 lrucache 或者 linkedhashmap就好了。

免费培训课:http://www.jinhusns.com/Products/Curriculum/?type=xcj

时间: 2024-10-11 16:32:22

android 网络加载图片,对图片资源进行优化,并且实现内存双缓存 + 磁盘缓存的相关文章

android 网络加载图片

通过网络链接加载网络图片 加权限,允许访问网络 <uses-permission android:name="android.permission.INTERNET"/> MainActivity package com.chuanxidemo.shaoxin.demo08; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.os.Bundle; imp

Android异步加载学习笔记之四:利用缓存优化网络加载图片及ListView加载优化

如果不做任何处理,直接用网络加载图片在网速快的情况下可能没什么不好的感觉,但是如果使用移动流量或是网络不好的时候,问题就来了,要么用户会抱怨流量使用太多,要么抱怨图片加载太慢,如论从哪个角度出发,都不是好的体验!要提高用户体验,我们就要使用缓存.Android中数据缓存的方式有很多,相关介绍的文章也比较多,比如http://blog.csdn.net/dahuaishu2010_/article/details/17093139和http://www.jb51.net/article/38162

三种基本网络加载图片方式

代码片段(6) [全屏查看所有代码] 1. [代码]普通加载网络方式     ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 public class NormalLoadPictrue {   

【iOS】网络加载图片缓存与SDWebImage

加载网络图片可以说是网络应用中必备的.如果单纯的去下载图片,而不去做多线程.缓存等技术去优化,加载图片时的效果与用户体验就会很差. 一.自己实现加载图片的方法 tips: *iOS中所有网络访问都是异步的.(自己开线程去下载) *普通为模型增加UIImage属性的方法做的是内存缓存(下次启动还需要从网络重新加载), 而要做本地缓存的话,还要自己手动存储网络上下载的图片. *为了加快访问, 还需要自己去弄缓存.(内存缓存或者本地缓存) *当图片没有下载完成时,还要设置占位图片. 以下代码用NSOp

网络多线程 ---实现网络加载图片

案例要求:网络加载图片,随机加载到设置好的视图上 实现的效果图如下: 具体代码如下: // //  ViewController.m //  0603---NSOperationQueue #import "ViewController.h" @interface ViewController () @property (nonatomic,strong) NSMutableArray * imageArray; @end @implementation ViewController

tableview加载图片的时候的优化之lazy(懒加载)模式and异步加载模式

iOS---tableview加载图片的时候的优化之lazy(懒加载)模式and异步加载模式举个例子,当我们在用网易新闻App时,看着那么多的新闻,并不是所有的都是我们感兴趣的,有的时候我们只是很快的滑过,想要快速的略过不喜欢的内容,但是只要滑动经过了,图片就开始加载了,这样用户体验就不太好,而且浪费内存.这个时候,我们就可以利用lazy加载技术,当界面滑动或者滑动减速的时候,都不进行图片加载,只有当用户不再滑动并且减速效果停止的时候,才进行加载.刚开始我异步加载图片利用SDWebImage来做

Android 异步加载图片,使用LruCache和SD卡或手机缓存,效果非常的流畅

转载请注明出处http://blog.csdn.net/xiaanming/article/details/9825113 异步加载图片的例子,网上也比较多,大部分用了HashMap<String, SoftReference<Drawable>> imageCache ,但是现在已经不再推荐使用这种方式了,因为从 Android 2.3 (API Level 9)开始,垃圾回收器会更倾向于回收持有软引用或弱引用的对象,这让软引用和弱引用变得不再可靠.另外,Android 3.0

LruCache:从网络加载图片缓存实例

OOM异常 堆内存用于存储实例对象,当程序不断创建对象,并且对象都有引用指向,那么垃圾回收机制就不会清理这些对象,当对象多到挤满堆内存的上限后,就产生OOM异常.Android系统为每个应用程序使用的内存设置了一个上限.这个上限值可以用下面的方法取得: long maxSize = Runtime.getRuntime().maxMemory(); OOM异常通常分为下面几种情况:1.内存泄漏导致的OOM:new出来的很多对象已经不需要了,但仍然有引用指向,所以垃圾回收机制无法回收. 其场景类似

iOS网络加载图片缓存策略之ASIDownloadCache缓存优化

在我们实际工程中,很多情况需要从网络上加载图片,然后将图片在imageview中显示出来,但每次都要从网络上请求,会严重影响用户体验,为了不是每次显示都需要从网上下载数据,希望将图片放到本地缓存,因此我们需要一个好的的缓存策略,今天我将我在项目工程中的实际经验分享给大家,我这里主要介绍一下强大的ASIHTTPRequest的缓存策略,以及使用方法. AD: 在我们实际工程中,很多情况需要从网络上加载图片,然后将图片在imageview中显示出来,但每次都要从网络上请求,会严重影响用户体验,为了不