经常会用到 网络文件 比如查看大图片数据 资源优化的问题,当然用开源的项目  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

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

  1. 【转】Android循环滚动广告条的完美实现,封装方便,平滑过渡,从网络加载图片,点击广告进入对应网址

    Android循环滚动广告条的完美实现,封装方便,平滑过渡,从网络加载图片,点击广告进入对应网址 关注finddreams,一起分享,一起进步: http://blog.csdn.net/finddr ...

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

    iOS网络加载图片缓存策略之ASIDownloadCache缓存优化   在我们实际工程中,很多情况需要从网络上加载图片,然后将图片在imageview中显示出来,但每次都要从网络上请求,会严重影响用 ...

  3. Android Glide加载图片时转换为圆形、圆角、毛玻璃等图片效果

     Android Glide加载图片时转换为圆形.圆角.毛玻璃等图片效果 附录1简单介绍了Android开源的图片加载框架.在实际的开发中,虽然Glide解决了快速加载图片的问题,但还有一个问题悬 ...

  4. swift 基础小结01 --delegate、Optional、GCD的使用、request请求、网络加载图片并保存到沙箱、闭包以及桥接

    本文主要记录swift中delegate的使用.“?!”Optional的概念.GCD的使用.request请求.网络加载图片并保存到沙箱.闭包以及桥接. 一.delegate的使用 swift中de ...

  5. 演化理解 Android 异步加载图片(转)

    演化理解 Android 异步加载图片(转)http://www.cnblogs.com/CJzhang/archive/2011/10/20/2218474.html

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

      Android 高手进阶(21)  版权声明:本文为博主原创文章,未经博主允许不得转载. 转载请注明出处http://blog.csdn.net/xiaanming/article/details ...

  7. 实例演示Android异步加载图片

    本文给大家演示异步加载图片的分析过程.让大家了解异步加载图片的好处,以及如何更新UI.首先给出main.xml布局文件:简单来说就是 LinearLayout 布局,其下放了2个TextView和5个 ...

  8. 实例演示Android异步加载图片(转)

    本文给大家演示异步加载图片的分析过程.让大家了解异步加载图片的好处,以及如何更新UI.首先给出main.xml布局文件:简单来说就是 LinearLayout 布局,其下放了2个TextView和5个 ...

  9. 演化理解 Android 异步加载图片

    原文:http://www.cnblogs.com/ghj1976/archive/2011/05/06/2038738.html#3018499 在学习"Android异步加载图像小结&q ...

随机推荐

  1. C#集合类型大盘点

    C#集体类型( Collections in C#) 集合是.NET FCL(Framework Class Library)中很重要的一部分,也是我们开发当中最常用到的功能之一,几乎是无处不在.俗话 ...

  2. WPF+通过配置文件生成菜单(Menu)+源码

    这个月做项目,遇到过一个通过配置文件来生成菜单的解决方案,感觉挺优雅的,特地放到博客园来,以飨读者. 说来惭愧,以前做的项目都没有这样用过,都是固定死了.如果后续有需要加入菜单,还得在重新修改UI,然 ...

  3. [Unity3D]自己动手重制坦克舰队ArmadaTank

    [Unity3D]自己动手重制坦克舰队ArmadaTank 我玩过一款坦克游戏ArmadaTank(坦克舰队),如下图所示 几个月前我尝试用Unity3D重制这款游戏,已经可以玩起来了.下面是在PC上 ...

  4. 2013 duilib入门简明教程 -- 响应按钮事件(4)

        上一个Hello World的教程里有一句代码是这样的:CControlUI *pWnd = new CButtonUI;     也就是说,其实那整块绿色背景区域都是按钮的区域.(这里简要介 ...

  5. 冒烟测试 smoking test

    冒烟测试的概念: 版权声明:本文为博主原创文章,未经博主允许不得转载. 冒烟测试既是对软件基本的功能进行测试,测试的对象是每一个新编译的需要正式测试的软件版本,目的是确认软件基本的功能正常,保证软件系 ...

  6. iOS--通讯录、蓝牙、内购、GameCenter、iCloud、Passbook等系统服务开发汇总

    iOS开发过程中有时候难免会使用iOS内置的一些应用软件和服务,例如QQ通讯录.微信电话本会使用iOS的通讯录,一些第三方软件会在应用内发送短信等.今天将和大家一起学习如何使用系统应用.使用系统服务: ...

  7. CSS系列:CSS的继承与层叠特性

    1. CSS的继承特性 所有的CSS语句都是基于各个标记直接的继承关系,CSS继承是指子标记会继承父标记的所有样式风格,并可以再父标记样式风格的基础上再加以修改,产生新的样式,而子标记的样式完全不会影 ...

  8. 【Win10 应用开发】扫描和连接Wi-fi网络

    老周今天带大家去“扫雷”了,别当真,是扫描并连接指定无线网络,时尚一点叫Wi-fi. 所以,今天的任务要求你的设备至少有1张无线网卡,目前老周没看到过有N张无线网卡的设备.像笔记本.平板等设备都可以, ...

  9. MySQL学习笔记九:存储过程,存储函数,触发器

    存储过程 1.存储过程由一组特定功能的SQL语句组成,对于大型应用程序优势较大,相对不使用存储过程,具有以下优点: a.性能提高,因为存储过程是预编译的,只需编译一次,以后调用就不须再编译 b.重用性 ...

  10. 在ubuntu server中安装和配置docker

    经过一段时间针对不同版本的学习,现在总结当前最新的安装配置过程(应该也是比较简单的) 如果不清楚什么是docker,请参考 https://www.docker.com/ 准备工作 建议在安装之前运行 ...