学习谷歌文档,总结如下:


1.图片加载框架的封装

1)利用HttpURLConnection来封装网络加载图片的方法

2)创建自定义的AsyncTask来封装1)中加载网络图片的方法,并显示到控件上。

3)暴露方法封装2)中自定义的加载并显示图片的AsyncTask

走完上面这几步,只需调用一个方法,就可以从网络上加载一张图片并且显示到控件上了。

解决List并发下载图片错位的问题

但是,谷歌文档中说上面代码会存在一个问题。就是如果在List里使用,复用的话,可能会发生图

图片错位的问题:就是某个item显示的图片,可能显示的图片是之前的item的图片。因为之前的这

张图片可能加载时间比较长,滑动后p_w_picpathview是复用的,所以后面的item可能会显示之前的item的

图片。


这种就是由于并发产生的问题,谷歌工程师是这么解决问题的:

1》定义一个类 class DownloadedDrawable extends ColorDrawable,然后将下载的异步任务

DownloadAsyncTask与其绑定起来。

publicstaticvoiddisplay(Contextcontext,Stringurl,ImageViewp_w_picpathView){BitmapbitmapFromMemCache=LruCacheUtil.getBitmapFromMemCache(url);if(bitmapFromMemCache!=null){p_w_picpathView.setImageBitmap(bitmapFromMemCache);}else{if(cancelPotentialDownload(url,p_w_picpathView)){BitmapDownloaderTasktask=newBitmapDownloaderTask(context,p_w_picpathView);DownloadedDrawabledownloadedDrawable=newDownloadedDrawable(task);p_w_picpathView.setImageDrawable(downloadedDrawable);task.execute(url);}}}

2》定义2个方法

BitmapDownloaderTask getBitmapDownloaderTask(ImageView p_w_picpathView)

--得到与ImageView绑定的异步下载任务

publicstaticBitmapDownloaderTaskgetBitmapDownloaderTask(ImageViewp_w_picpathView){if(p_w_picpathView!=null){Drawabledrawable=p_w_picpathView.getDrawable();if(drawableinstanceofDownloadedDrawable){DownloadedDrawabledownloadedDrawable=(DownloadedDrawable)drawable;returndownloadedDrawable.getBitmapDownloaderTask();}}returnnull;}


boolean cancelPotentialDownload(String url, ImageView p_w_picpathView)

--取消可能正在进行的下载,并返回是否已经取消。

如果与p_w_picpathView绑定的下载任务不为空,再判断与ImageView绑定的异步下载任务的URL,如果

为null或者是与当前方法传递进来URL不一致,说明异步下载任务正在执行之前的下载,就取消任

务,否则说明任务正在执行中且url一致,就不重新开启任务。

privatestaticbooleancancelPotentialDownload(Stringurl,ImageViewp_w_picpathView){BitmapDownloaderTaskbitmapDownloaderTask=BitmapDownloaderTask.getBitmapDownloaderTask(p_w_picpathView);if(bitmapDownloaderTask!=null){StringbitmapUrl=bitmapDownloaderTask.url;if((bitmapUrl==null)||(!bitmapUrl.equals(url))){bitmapDownloaderTask.cancel(true);}else{//ThesameURLisalreadybeingdownloaded.returnfalse;}}returntrue;}

解决图片缓存的问题

1》用内存来缓存,使用LruCache这个类。

内存的特点:

内存加载速度比较快,但是内存在开关机之后会被回收,缓存的数据会消失。

底层:

LinkedHashMap来实现存储

实现原理:

当从url下载图片之前,先判断缓存中存不存在图片,如果存在直接加载图片,不存在则

去网络请求图片。

当AsyncTask下载完图片之后,如果不为null,就存放到缓存中。

于是我写了个工具类LruCacheUtils来完成图片的缓存

publicclassLruCacheUtil{//LruCacheforbitmapprivatestaticLruCache<String,Bitmap>mMemoryCache;static{//GetmaxavailableVMmemory,exceedingthisamountwillthrowan//OutOfMemoryexception.StoredinkilobytesasLruCachetakesan//intinitsconstructor.finalintmaxMemory=(int)(Runtime.getRuntime().maxMemory()/1024);//Use1/8thoftheavailablememoryforthismemorycache.finalintcacheSize=maxMemory/8;mMemoryCache=newLruCache<String,Bitmap>(cacheSize){@TargetApi(Build.VERSION_CODES.HONEYCOMB_MR1)@OverrideprotectedintsizeOf(Stringkey,Bitmapbitmap){//Thecachesizewillbemeasuredinkilobytesratherthan//numberofitems.returnbitmap.getByteCount()/1024;}};}publicstaticvoidaddBitmapToMemoryCache(Stringkey,Bitmapbitmap){if(getBitmapFromMemCache(key)==null){mMemoryCache.put(key,bitmap);}}publicstaticBitmapgetBitmapFromMemCache(Stringkey){returnmMemoryCache.get(key);}}

2》使用磁盘(Disk)来缓存,使用DiskLruCache(这个类google文档里并没有提供)

Android DiskLruCache 源码解析 硬盘缓存的绝佳方案

http://blog.csdn.net/lmj623565791/article/details/47251585

下载链接

http://http://www.oschina.net/p/disklrucache

Android本地缓存DiskLruCache完整详细学习示例

http://www.2cto.com/kf/201501/368172.html

虽然利用内存来缓存,加载图片的时候速度比较快,但是像GridView会很快地占满内存。当应

用非正常关闭(如被电话应用打断、运行在后台的时候被杀死)会导致cache被销毁清空。

注意:获取图片应该在后台进行

Of course, fetching p_w_picpaths from disk is slower than loading from memory and should be done in a

background thread, as disk read times can be unpredictable.(from google doc)

缓存位置:

有外部存储设备就存放到外部存储设备中,否则存放到应用包名目录下。


2.布局优化

sdk下的一些工具并不是专门针对Eclipse的,Android Studio也可以使用。

sdk/tools下的工具Hierarchy Viewer

http://wear.techbrood.com/training/improving-layouts/optimizing-layout.html#Inspect

爽处1:可以查看布局结构某个节点的3个方法Measure、Layout、Draw执行所需要的时间,这样

如果某个item的加载时间比较长,你就应该要优化了。

使用这个工具可能会遇到的问题:

问题:使用Hierarchyviewer,measure、layout、draw时间未显示?

解决办法:点击菜单ProfileNode,重新加载之后就有了

用Hierarchyviewer,measure、layout、draw时间未显示?