上篇文章中我们提到了图片加载其实是用了三条线程,如果没看过的同学可以先了解下这里。
fackbook的Fresco的Image Pipeline以及自身的缓存机制
那么今天我们就来探索一下如何在代码中改变图片实现的状态和内容,前面我们已经使用过SimpleDraweeView这个控件了,显示图片的时候直接写了一个setImageURI(uri),Fresco不仅仅提供了这一个方法来显示图片,它还提供了setController(controller)方法加载图片
DraweeController controller = Fresco.newDraweeControllerBuilder()
.setUri(uri)
.build();
imageView.setController(controller);
那有的人会问,如何加载监听?Controller?没错,就是它~
ControllerListener listener = new BaseControllerListener(){
@Override
public void onFinalImageSet(String id,Object imageInfo,Animatable animatable) {
super.onFinalImageSet(id,imageInfo,animatable);
}
@Override
public void onFailure(String id,Throwable throwable) {
super.onFailure(id,throwable);
}
@Override
public void onIntermediateImageFailed(String id,Throwable throwable) {
super.onIntermediateImageFailed(id,throwable);
}
};
DraweeController controller = Fresco.newDraweeControllerBuilder()
.setUri(uri)
.setControllerListener(listener)
.build();
imageView.setController(controller);
建议使用
BaseControllerListener
图片加载成功或者失败,会执行里面的方法,其中图片加载成功时会执行onFinalImageSet方法,图片加载失败时会执行onFailure方法,如果图片设置渐进式,onIntermediateImageFailed会被回调
加载uri之后,如何实现在xml中的效果呢?
GenericDraweeHierarchy hierarchy = new GenericDraweeHierarchyBuilder(getResources()) .setFadeDuration(300) .setBackground(getDrawable(R.drawable.ic_launcher)) .setPlaceholderImage(getDrawable(R.drawable.ic_launcher)) .setFailureImage(getDrawable(R.drawable.ic_launcher)) .build(); imageView.setHierarchy(hierarchy);
其实使用到的方法很多,你在xml中用到的都可以在这里设置,有些在xml中不能设置的在这里也是可以的。
例如,设置多张背景图片,设置多张叠加图,这里都可以实现,不过有一点必须注意,就是DraweeHiererchy创建时比较耗时,所以要多次利用。那如何使用会比较好?
GenericDraweeHierarchy hierarchyOLD = imageView.getHierarchy();直接拿到对象--->hierarchyOLD
首先是渐进式图片加载,这方面的功能充分考虑了网络比较慢的情况下,用户不至于一致在等,最起码能看到模糊的照片,这个所谓的渐进式加载就是说用户从图片加载之后,图片会从模糊到清晰的一个渐变过程,当然这个过程仅限于从网络加载图片,本地或者缓存等地方的图片也不需要渐进式加载,没有意义.
ProgressiveJpegConfig config = new ProgressiveJpegConfig() { @Override public int getNextScanNumberToDecode(int i) { return 0; } @Override public QualityInfo getQualityInfo(int i) { return null; } }; ImagePipelineConfig imagePipelineConfig = ImagePipelineConfig.newBuilder(this) .setProgressiveJpegConfig(config) .build(); Fresco.initialize(getApplicationContext(),imagePipelineConfig);
ProgressiveJpegConfig config1= new SimpleProgressiveJpegConfig(list,2);//当然你也可以使用这个
FLog.setMinimumLoggingLevel(FLog.VERBOSE); Set<RequestListener> listeners = new HashSet<>(); listeners.add(new RequestLoggingListener()); ImagePipelineConfig config = ImagePipelineConfig.newBuilder(this) .setRequestListeners(listeners) .build(); Fresco.initialize(this,config); setContentView(R.layout.activity_main); mProgressiveJpegView = (SimpleDraweeView) findViewById(R.id.my_image_view); Uri uri = Uri.parse("http://pooyak.com/p/progjpeg/jpegload.cgi?o=1"); ImageRequest request = ImageRequestBuilder.newBuilderWithSource(uri) .setProgressiveRenderingEnabled(true) .build(); DraweeController controller = Fresco.newDraweeControllerBuilder() .setImageRequest(request) .build(); mProgressiveJpegView.setController(controller);
最后就是请求了 ~~
ImageRequest request = ImageRequestBuilder .newBuilderWithSource(uri) .setProgressiveRenderingEnabled(true) .build(); PipelineDraweeController controller = (PipelineDraweeController) Fresco.newDraweeControllerBuilder() .setImageRequest(request) .setOldController(imageView.getController()) .build(); imageView.setController(controller);
那么,假设我们要下载一张比较大的图片,下载很慢的情况下有些服务器会提供一张缩略图,是服务器提供缩略图,服务器!!重要的事情要说三遍!!同样,Fresco也支持这种方法,记住,在controller中他们提供了两个不同的方法setLowResImageRequest和setImageRequest,顾名思义! 个人认为这个框架最巧妙的地方,就是把bitmap保存到ashmen,不会启动gc,使的界面不会因为gc而卡死。Fresco使用三级缓存,第一级缓存就是保存bitmap,第二级缓存保存在内存,但是没有解码,使用时需要界面,第三级缓存就是保存在本地文件,同样文件也未解码,使用的时候要先解码啦!
上面谈到的保存的很多内容都未解码,这也是fresco默认使用3个线程的原因,一个线程用来加载uri,一个线程用来解码,最后一个你知道它做什么,其余的内容后续会更新。