大家好,关于bitdownloader很多朋友都还不太明白,不过没关系,因为今天小编就来为大家分享关于downloader是什么病毒啊急救!!!的知识点,相信应该可以解决大家的一些困惑和问题,如果碰巧可以解决您的问题,还望关注下本站哦,希望对各位有所帮助!
本文目录
universal imageloader 怎么修改源码image downloade怎么用的AsyncTask中的isCancelled是什么意思downloader是什么病毒啊急救!!!universal imageloader 怎么修改源码AndroidUniversalImageLoader源码分析
本文为Android开源项目源码解析中AndroidUniversalImageLoader部分
项目地址:Android-Universal-Image-Loader,分析的版本:eb794c3,Demo地址:UILDemo
分析者:huxian99,校对者:Grumoon、Trinea,校对状态:完成
1.功能介绍
1.1AndroidUniversalImageLoader
AndroidUniversalImageLoader是一个强大的、可高度定制的图片缓存,本文简称为UIL。
简单的说UIL就做了一件事——获取图片并显示在相应的控件上。
1.2基本使用
1.2.1初始化
添加完依赖后在Application或Activity中初始化ImageLoader,如下:
publicclassYourApplicationextendsApplication{
@Override
publicvoidonCreate(){
super.onCreate();
ImageLoaderConfigurationconfiguration=newImageLoaderConfiguration.Builder(this)
//添加你的配置需求
.build();
ImageLoader.getInstance().init(configuration);
}
}
其中configuration表示ImageLoader的配置信息,可包括图片最大尺寸、线程池、缓存、下载器、解码器等等。
1.2.2Manifest配置
<manifest>
<uses-permissionandroid:name="android.permission.INTERNET"/>
<uses-permissionandroid:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<application
android:name=".YourApplication"
……>
……
</application>
</manifest>
添加网络权限。如果允许磁盘缓存,需要添加写外设的权限。
1.2.3下载显示图片
下载图片,解析为Bitmap并在ImageView中显示。
imageLoader.displayImage(imageUri,imageView);
下载图片,解析为Bitmap传递给回调接口。
imageLoader.loadImage(imageUri,newSimpleImageLoadingListener(){
@Override
publicvoidonLoadingComplete(StringimageUri,Viewview,BitmaploadedImage){
//图片处理
}
});
以上是简单使用,更复杂API见本文详细设计。
1.3特点
可配置度高。支持任务线程池、下载器、解码器、内存及磁盘缓存、显示选项等等的配置。
包含内存缓存和磁盘缓存两级缓存。
支持多线程,支持异步和同步加载。
支持多种缓存算法、下载进度监听、ListView图片错乱解决等。
2.总体设计
2.1.总体设计图
上面是UIL的总体设计图。整个库分为ImageLoaderEngine,Cache及ImageDownloader,ImageDecoder,BitmapDisplayer,BitmapProcessor五大模块,其中Cache分为MemoryCache和DiskCache两部分。
简单的讲就是ImageLoader收到加载及显示图片的任务,并将它交给ImageLoaderEngine,ImageLoaderEngine分发任务到具体线程池去执行,任务通过Cache及ImageDownloader获取图片,中间可能经过BitmapProcessor和ImageDecoder处理,最终转换为Bitmap交给BitmapDisplayer在ImageAware中显示。
2.2.UIL中的概念
简单介绍一些概念,在4.详细设计中会仔细介绍。
ImageLoaderEngine:任务分发器,负责分发LoadAndDisplayImageTask和ProcessAndDisplayImageTask给具体的线程池去执行,本文中也称其为engine,具体参考4.2.6ImageLoaderEngine.java。
ImageAware:显示图片的对象,可以是ImageView等,具体参考4.2.9ImageAware.java。
ImageDownloader:图片下载器,负责从图片的各个来源获取输入流,具体参考4.2.22ImageDownloader.java。
Cache:图片缓存,分为MemoryCache和DiskCache两部分。
MemoryCache:内存图片缓存,可向内存缓存缓存图片或从内存缓存读取图片,具体参考4.2.24MemoryCache.java。
DiskCache:本地图片缓存,可向本地磁盘缓存保存图片或从本地磁盘读取图片,具体参考4.2.38DiskCache.java。
ImageDecoder:图片解码器,负责将图片输入流InputStream转换为Bitmap对象,具体参考4.2.53ImageDecoder.java。
BitmapProcessor:图片处理器,负责从缓存读取或写入前对图片进行处理。具体参考4.2.61BitmapProcessor.java。
BitmapDisplayer:将Bitmap对象显示在相应的控件ImageAware上,具体参考4.2.56BitmapDisplayer.java。
LoadAndDisplayImageTask:用于加载并显示图片的任务,具体参考4.2.20LoadAndDisplayImageTask.java。
ProcessAndDisplayImageTask:用于处理并显示图片的任务,具体参考4.2.19ProcessAndDisplayImageTask.java。
DisplayBitmapTask:用于显示图片的任务,具体参考4.2.18DisplayBitmapTask.java。
3.流程图
上图为图片加载及显示流程图,在uil库中给出,这里用中文重新画出。
4.详细设计
4.1类关系图
4.2核心类功能介绍
4.2.1ImageLoader.java
图片加载器,对外的主要API,采取了单例模式,用于图片的加载和显示。
主要函数:
(1).getInstance()
得到ImageLoader的单例。通过双层是否为null判断提高性能。
(2).init(ImageLoaderConfigurationconfiguration)
初始化配置参数,参数configuration为ImageLoader的配置信息,包括图片最大尺寸、任务线程池、磁盘缓存、下载器、解码器等等。
实现中会初始化ImageLoaderEngineengine属性,该属性为任务分发器。
(3).displayImage(Stringuri,ImageAwareimageAware,DisplayImageOptionsoptions,ImageLoadingListenerlistener,ImageLoadingProgressListenerprogressListener)
加载并显示图片或加载并执行回调接口。ImageLoader加载图片主要分为三类接口:
displayImage(…)表示异步加载并显示图片到对应的ImageAware上。
loadImage(…)表示异步加载图片并执行回调接口。
loadImageSync(…)表示同步加载图片。
以上三类接口最终都会调用到这个函数进行图片加载。函数参数解释如下:
uri:图片的uri。uri支持多种来源的图片,包括http、https、file、content、assets、drawable及自定义,具体介绍可见ImageDownloader。
imageAware:一个接口,表示需要加载图片的对象,可包装View。
options:图片显示的配置项。比如加载前、加载中、加载失败应该显示的占位图片,图片是否需要在磁盘缓存,是否需要在内存缓存等。
listener:图片加载各种时刻的回调接口,包括开始加载、加载失败、加载成功、取消加载四个时刻的回调函数。
progressListener:图片加载进度的回调接口。
函数流程图如下:
4.2.2ImageLoaderConfiguration.java
ImageLoader的配置信息,包括图片最大尺寸、线程池、缓存、下载器、解码器等等。
主要属性:
(1).Resourcesresources
程序本地资源访问器,用于加载DisplayImageOptions中设置的一些App中图片资源。
(2).intmaxImageWidthForMemoryCache
内存缓存的图片最大宽度。
(3).intmaxImageHeightForMemoryCache
内存缓存的图片最大高度。
(4).intmaxImageWidthForDiskCache
磁盘缓存的图片最大宽度。
(5).intmaxImageHeightForDiskCache
磁盘缓存的图片最大高度。
(6).BitmapProcessorprocessorForDiskCache
图片处理器,用于处理从磁盘缓存中读取到的图片。
(7).ExecutortaskExecutor
ImageLoaderEngine中用于执行从源获取图片任务的Executor。
(18).ExecutortaskExecutorForCachedImages
ImageLoaderEngine中用于执行从缓存获取图片任务的Executor。
(19).booleancustomExecutor
用户是否自定义了上面的taskExecutor。
(20).booleancustomExecutorForCachedImages
用户是否自定义了上面的taskExecutorForCachedImages。
(21).intthreadPoolSize
上面两个默认线程池的核心池大小,即最大并发数。
(22).intthreadPriority
上面两个默认线程池的线程优先级。
(23).QueueProcessingTypetasksProcessingType
上面两个默认线程池的线程队列类型。目前只有FIFO,LIFO两种可供选择。
(24).MemoryCachememoryCache
图片内存缓存。
(25).DiskCachediskCache
图片磁盘缓存,一般放在SD卡。
(26).ImageDownloaderdownloader
图片下载器。
(27).ImageDecoderdecoder
图片解码器,内部可使用我们常用的BitmapFactory.decode(…)将图片资源解码成Bitmap对象。
(28).DisplayImageOptionsdefaultDisplayImageOptions
图片显示的配置项。比如加载前、加载中、加载失败应该显示的占位图片,图片是否需要在磁盘缓存,是否需要在内存缓存等。
(29).ImageDownloadernetworkDeniedDownloader
不允许访问网络的图片下载器。
(30).ImageDownloaderslowNetworkDownloader
慢网络情况下的图片下载器。
4.2.3ImageLoaderConfiguration.Builder.java静态内部类
Builder模式,用于构造参数繁多的ImageLoaderConfiguration。
其属性与ImageLoaderConfiguration类似,函数多是属性设置函数。
主要函数及含义:
(1).build()
按照配置,生成ImageLoaderConfiguration。代码如下:
publicImageLoaderConfigurationbuild(){
initEmptyFieldsWithDefaultValues();
returnnewImageLoaderConfiguration(this);
}
(2).initEmptyFieldsWithDefaultValues()
初始化值为null的属性。若用户没有配置相关项,UIL会通过调用DefaultConfigurationFactory中的函数返回一个默认值当配置。
taskExecutorForCachedImages、taskExecutor及ImageLoaderEngine的taskDistributor的默认值如下:
parameters
taskDistributor
taskExecutorForCachedImages/taskExecutor
corePoolSize03
maximumPoolSizeInteger.MAX_VALUE3
keepAliveTime600
unitSECONDSMILLISECONDS
workQueueSynchronousQueueLIFOLinkedBlockingDeque/LinkedBlockingQueue
priority53
diskCacheFileNameGenerator默认值为HashCodeFileNameGenerator。
memoryCache默认值为LruMemoryCache。如果内存缓存不允许缓存一张图片的多个尺寸,则用FuzzyKeyMemoryCache做封装,同一个图片新的尺寸会覆盖缓存中该图片老的尺寸。
diskCache默认值与diskCacheSize和diskCacheFileCount值有关,如果他们有一个大于0,则默认为LruDiskCache,否则使用无大小限制的UnlimitedDiskCache。
downloader默认值为BaseImageDownloader。
decoder默认值为BaseImageDecoder。
详细及其他属性默认值请到DefaultConfigurationFactory中查看。
(3).denyCacheImageMultipleSizesInMemory()
设置内存缓存不允许缓存一张图片的多个尺寸,默认允许。
后面会讲到View的getWidth()在初始化前后的不同值与这个设置的关系。
(4).diskCacheSize(intmaxCacheSize)
设置磁盘缓存的最大字节数,如果大于0或者下面的maxFileCount大于0,默认的DiskCache会用LruDiskCache,否则使用无大小限制的UnlimitedDiskCache。
(5).diskCacheFileCount(intmaxFileCount)
设置磁盘缓存文件夹下最大文件数,如果大于0或者上面的maxCacheSize大于0,默认的DiskCache会用LruDiskCache,否则使用无大小限制的UnlimitedDiskCache。
4.2.4ImageLoaderConfiguration.NetworkDeniedImageDownloader.java静态内部类
不允许访问网络的图片下载器,实现了ImageDownloader接口。
实现也比较简单,包装一个ImageDownloader对象,通过在getStream(…)函数中禁止Http和HttpsScheme禁止网络访问,如下:
@Override
publicInputStreamgetStream(StringimageUri,Objectextra)throwsIOException{
switch(Scheme.ofUri(imageUri)){
caseHTTP:
caseHTTPS:
thrownewIllegalStateException();
default:
returnwrappedDownloader.getStream(imageUri,extra);
}
}
4.2.5ImageLoaderConfiguration.SlowNetworkImageDownloader.java静态内部类
慢网络情况下的图片下载器,实现了ImageDownloader接口。
通过包装一个ImageDownloader对象实现,在getStream(…)函数中当Scheme为Http和Https时,用FlushedInputStream代替InputStream处理慢网络情况,具体见后面FlushedInputStream的介绍。
4.2.6ImageLoaderEngine.java
LoadAndDisplayImageTask和ProcessAndDisplayImageTask任务分发器,负责分发任务给具体的线程池。
主要属性:
(1).ImageLoaderConfigurationconfiguration
ImageLoader的配置信息,可包括图片最大尺寸、线程池、缓存、下载器、解码器等等。
(2).ExecutortaskExecutor
用于执行从源获取图片任务的Executor,为configuration中的taskExecutor,如果为null,则会调用DefaultConfigurationFactory.createExecutor(…)根据配置返回一个默认的线程池。
(3).ExecutortaskExecutorForCachedImages
用于执行从缓存获取图片任务的Executor,为configuration中的taskExecutorForCachedImages,如果为null,则会调用DefaultConfigurationFactory.createExecutor(…)根据配置返回一个默认的线程池。
(4).ExecutortaskDistributor
任务分发线程池,任务指LoadAndDisplayImageTask和ProcessAndDisplayImageTask,因为只需要分发给上面的两个Executor去执行任务,不存在较耗时或阻塞操作,所以用无并发数(Int最大值)限制的线程池即可。
(5).MapcacheKeysForImageAwares
ImageAware与内存缓存key对应的map,key为ImageAware的id,value为内存缓存的key。
(6).MapuriLocks
图片正在加载的重入锁map,key为图片的uri,value为标识其正在加载的重入锁。
(7).AtomicBooleanpaused
是否被暂停。如果为true,则所有新的加载或显示任务都会等待直到取消暂停(为false)。
(8).AtomicBooleannetworkDenied
是否不允许访问网络,如果为true,通过ImageLoadingListener.onLoadingFailed(…)获取图片,则所有不在缓存中需要网络访问的请求都会失败,返回失败原因为网络访问被禁止。
(9).AtomicBooleanslowNetwork
是否是慢网络情况,如果为true,则自动调用SlowNetworkImageDownloader下载图片。
(10).ObjectpauseLock
image downloade怎么用的主要对ImageDownloader分析:
BitmapdownloadBitmap(Stringurl);//从网站下载一幅图片,比较简单
HttpClient:
AndroidHttpClient:ApacheDefaultHttpClient的子类,已经配置好默认的合理设置和Android注册过的方案。不能直接创建对象。
AndroidHttpClientnewInstance(StringuserAgent,Contextcontext)创建一个新HttpClient对象。
HttpResponse:一个HTTP应答。
HttpEntitygetEntity(),获得应答的消息实例
HttpEntity:一个可以发送接收HTTP消息的实例。
在一些情况下,javaDoc根据它们的内容来源把entity分三种:streamed,即内容来源是数据流,一般不可重复的;self-contained,内容来自内
存也意味着和连接以及其他entities没有关系,一般可重复;wrapping,内容从另一个entity获得。
InputStreamgetContent():创建实例的一个新的InputStream对象
consumeContent():这个方法被调用意味着这个实例的内容不再被请求了,而该实例分配的所有资源都会被释放。
但是在BitmapFactory.decodeStream之前版本的bug可能会阻止代码进行慢连接,而newFlushedInputStream(inputStream)方法可以解决这个问题。
staticclassFlushedInputStreamextendsFilterInputStream;其中里面的skip函数是为了使在以后的读输入流时准确的跳过n个字节。
staticclassFlushedInputStreamextendsFilterInputStream{
publicFlushedInputStream(InputStreaminputStream){
super(inputStream);
}
@Override
publiclongskip(longn)throwsIOException{
longtotalBytesSkipped=0L;
while(totalBytesSkipped<n){
longbytesSkipped=in.skip(n-totalBytesSkipped);
if(bytesSkipped==0L){
intbyte=read();//read()只读一个字节,但返回0~255的随机数
if(byte<0){
break;//到文件结尾
}else{
bytesSkipped=1;//读一个字节,这里当跳过0个字节时为什么要读一个字节不是太懂……
}
}
totalBytesSkipped+=bytesSkipped;
}
returntotalBytesSkipped;
}
}
如果在ListAdapter的getView方法中直接下载图片,效果会很卡,因为每一个新图像的显示都要等图像下载下来。
非常遗憾的是,AndroidHttpClient竟然不能在主线程里运行,否则会显示"ThisthreadforbidsHTTPrequests"错误信息。对于AsyncTask类,它提供其中一个最简单的方法来使新任务脱离UI线程运行。
我们创建了一个ImageDownloader类来负责生成这些新的下载任务(task),它提供download方法来分配一张从URL下载的图片到对应的ImageView中。
publicclassImageDownloader{
publicvoiddownload(Stringurl,ImageViewimageView){
BitmapDownloaderTasktask=newBitmapDownloaderTask(imageView);
task.execute(url);
}
}
BitmapDownloaderTask是AsyncTask的子类,用来实际下载图片的。调用execute(url)来运行它,能够立即返回结果,这也是UI线程调用它的主要原因。
其中doInBackground方法中调用了downloadBitmap来下载图片,onPostExecute是当下载结束时UI线程调用的,将存储在BitmapDownloaderTask中的imageView和下载的Bitmap相关联,而这个ImageView是一个弱引用,可以被系统回收,所以要在onpostExecute中检查弱引用和这个imageView不为空。
classBitmapDownloaderTaskextendsAsyncTask<String,Void,Bitmap>{
privateStringurl;
privatefinalWeakReference<ImageView>imageViewReference;
publicBitmapDownloaderTask(ImageViewimageView){
imageViewReference=newWeakReference<ImageView>(imageView);
}
@Override
//Actualdownloadmethod,runinthetaskthread
protectedBitmapdoInBackground(String...params){
//paramscomesfromtheexecute()call:params[0]istheurl.
returndownloadBitmap(params[0]);
}
@Override
//Oncetheimageisdownloaded,associatesittotheimageView
protectedvoidonPostExecute(Bitmapbitmap){
if(isCancelled()){
bitmap=null;
}
if(imageViewReference!=null){
ImageViewimageView=imageViewReference.get();
if(imageView!=null){
BitmapDownloaderTaskbitmapDownloaderTask=getBitmapDownloaderTask(imageView);
//ChangebitmaponlyifthisprocessisstillassociatedwiththisImageView
if(this==bitmapDownloaderTask){
imageView.setImageBitmap(bitmap);
}
}
}
}
}
对于ListView上的图像浏览,当用户快速滑动ListView时,某一个ImageView对象会被用到很多次,每一次显示都会触发一个下载,然后改变对应的图片。和大多数并行应用一样,有顺序相关的问题。在这个程序中,不能保证下载会按开始的顺序结束,有可能先开始的后下载完,“Theresultisthattheimagefinallydisplayedinthelistmaycomefromapreviousitem,whichsimplyhappenedtohavetakenlongertodownload.”结果就是,由于与该item对应的网络图片下载慢,导致该item位置还暂时显示着之前的item显示的图片(还没被刷新,有可能长时间不被刷新)
为了解决这个问题,我们应该记住下载的顺序,使得最后的下载会被有效地显示,要让每一个ImageView记住它们的上一次下载任务。因此我们给出了DownloadedDrawable类,向ImageView中加入对对应下载任务的弱引用来暂时绑定正在下载图片的ImageView。
staticclassDownloadedDrawableextendsColorDrawable;//该类包含了一个对下载的弱引用
staticclassDownloadedDrawableextendsColorDrawable{
privatefinalWeakReference<BitmapDownloaderTask>bitmapDownloaderTaskReference;
publicDownloadedDrawable(BitmapDownloaderTaskbitmapDownloaderTask){
super(Color.BLACK);
bitmapDownloaderTaskReference=
newWeakReference<BitmapDownloaderTask>(bitmapDownloaderTask);
}
publicBitmapDownloaderTaskgetBitmapDownloaderTask(){
returnbitmapDownloaderTaskReference.get();
}
}
上面ImageDownload中的download修改为:
publicvoiddownload(Stringurl,ImageViewimageView){
if(cancelPotentialDownload(url,imageView)){
BitmapDownloaderTasktask=newBitmapDownloaderTask(imageView);
DownloadedDrawabledownloadedDrawable=newDownloadedDrawable(task);
imageView.setImageDrawable(downloadedDrawable);
task.execute(url);
}
}
privatestaticBitmapDownloaderTaskgetBitmapDownloaderTask(ImageViewimageview);
//通过ImageView得到对应的下载
privatestaticBitmapDownloaderTaskgetBitmapDownloaderTask(ImageViewimageView){
if(imageView!=null){
Drawabledrawable=imageView.getDrawable();
if(drawableinstanceofDownloadedDrawable){
DownloadedDrawabledownloadedDrawable=(DownloadedDrawable)drawable;
returndownloadedDrawable.getBitmapDownloaderTask();
}
}
returnnull;
}
下面总结下载过程:
download(url,imageview)——>
@创建一个和该imageview相对应的下载任务,这个任务对imageview进行弱引用
@创建与这个任务相对应的DownloadedDrawable,对这个任务弱引用
@imageview加载DownloadedDrawable
@执行下载任务,下载对应url的图像——execute(url)进入下载任务类
在下载任务类中:
——>doInBackground===>downloadBitmap(url)下载图片,结果Bitmap作为下面的参数
——>onPostExcute(Bitmap)
@获得任务引用的imageview
@通过DownloadedDrawable获得该imageview所对应的任务
@如果当前任务是这个imageview所对应的任务,则设置这个imageview的图片为下载下
来的Bitmap
imageview和任务相互弱引用,形成绑定关系
AsyncTask中的isCancelled是什么意思调用了cancel()方法,就是说你已经调用了cancel()方法,也就会把isCanceled的值改变,
但是你看一个cancel()解释,就会发现这个方法不一定起作用,但是一定会通知这个一步类已经取消了,也就是isCancelled方法变为true。自己打一下log就明白了
downloader是什么病毒啊急救!!!楼上说什么啊
downloader是下载器木马
建议你安全模式下使用主流杀毒软件的最新版杀毒
没有杀毒软件的化到这里下载
有今天最新的瑞星
http://www.luckfish.net/rising.htm
关于bitdownloader到此分享完毕,希望能帮助到您。