文章目录

之前有写文章说别人对网上文章的看法,这次写的是我对网上文章的看法。一直以来对网上的文章的说法都抱有怀疑态度,一般都是把网上的东西作为参考,找准关键的地方,他的说法与自己写的有什么区别?一对比就知道哪些地方有欠缺,是什么原因。而不是直接copy过来使用。

以下这段内容可以选择忽略。

举个前几天在项目中遇到的例子。在android中捕获崩溃日志看到了将Throwable对象转换成字符串,写了很大一串。心想这段代码肯定来自网络,写这篇文章的时候去搜索了一下,果然。因为系统已经提供了将Throwable对象转换为字符串的方法,只需要调用就行,一行代码就可以搞定,有的甚至把android.util.Log输出Throwable对象的方式重新再写了一遍,解决问题的思路很赞。但如果再多看一眼,Log类中提供了getStackTraceString(Throwable)静态方法,方便处理这种事情,而且这个方法是从API Level 1开始就有。

OK,回到主题上来。事情的起因是项目中的一个bug。

项目中有一个滚动的Gallery查看大图,还有一个将图片保存到本地功能。但保存图片时会概率性失败,这个问题是测试反馈的,而且概率很高。自己测试发现进这个界面保存当前看到的这张图片能成功,后面每次保存都失败。

跟踪代码发现失败的原因是从SD卡中Fresco库缓存取图片时,图片不存在,所以保存失败。那为什么保存当前图片成功?

于是将缓存目录下面的内容都用日志打了出来。以下代码在每次图片加载完后就会把缓存内容都以LOG方式输出。

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
final PhotoDraweeView photoDraweeView = new PhotoDraweeView(context);
final PipelineDraweeControllerBuilder controller = Fresco.newDraweeControllerBuilder();
controller.setUri(uri); // 图片请求的URL地址
controller.setAutoPlayAnimations(true);
controller.setOldController(photoDraweeView.getController());
controller.setControllerListener(new BaseControllerListener<ImageInfo>() {
@Override
public void onFinalImageSet(String id, ImageInfo imageInfo, Animatable animatable) {
super.onFinalImageSet(id, imageInfo, animatable);
if (imageInfo == null) {
return;
}
FileBinaryResource resource = (FileBinaryResource) ImagePipelineFactory.getInstance().getMainFileCache().getResource(DefaultCacheKeyFactory.getInstance().getEncodedCacheKey(controller.getImageRequest(), null));
if (BuildConfig.DEBUG) {
Log.d("may", "resource: " + resource);
}
try {
List<DiskStorage.DiskDumpInfoEntry> list = Fresco.getImagePipelineFactory().getMainFileCache().getDumpInfo().entries;
if (list != null && !list.isEmpty()) {
for (DiskStorage.DiskDumpInfoEntry info : list) {
Log.d("may", "size: " + info.size + ", type: " + info.type + ", path: " + info.path + ", fb: " + info.firstBits);
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void onIntermediateImageSet(String id, ImageInfo imageInfo) {
}
@Override
public void onFailure(String id, Throwable throwable) {
}
});

以下是输出的LOG,

1
2
3
4
5
6
7
8
[onFinalImageSet, 314]:resource: com.facebook.binaryresource.FileBinaryResource@2f8cf0a9
[onFinalImageSet, 321]:size: 1580616.0, type: jpg, path: imgcache/v2.ols100.1/3/3qC9ts9ad_tJcsN1ot7Ort5YQ9A.cnt, fb:
[onFinalImageSet, 314]:resource: com.facebook.binaryresource.FileBinaryResource@411bafa9
[onFinalImageSet, 321]:size: 1.0461388E7, type: jpg, path: imgcache/v2.ols100.1/24/r0c37nN9TT6P-HU0hoYwm_ZU5K4.cnt, fb:
[onFinalImageSet, 314]:resource: com.facebook.binaryresource.FileBinaryResource@6d7fddcf
[onFinalImageSet, 321]:size: 1622679.0, type: jpg, path: imgcache/v2.ols100.1/1/BYrt44bfrnqXpdkx5x4p1W_RsTY.cnt, fb:
[onFinalImageSet, 314]:resource: com.facebook.binaryresource.FileBinaryResource@bfbbc062
[onFinalImageSet, 321]:size: 1127054.0, type: jpg, path: imgcache/v2.ols100.1/96/mhZk2iyqbM0iKt2RmDV0aKT0o5Q.cnt, fb:

从上面的日志中看出图片都缓存到了指定的路径,但是从文件管理器中去查看v2.ols100.1目录下面的对应目录基本都为空,只有一个目录中有缓存图片,整个目录大小只有几百KB。感觉图片只缓存了一张,其它的都没有缓存到外部存储空间上来。

看了一下存储空间,还有几个G,不存在空间不足。与图片大小有关系?换了大图试试,也还是这样。开始怀疑与Fresco相关的代码,于是找到了Fresco初始化代码,如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
DiskCacheConfig.Builder builder = DiskCacheConfig.newBuilder(this);
builder.setMaxCacheSize(150);
builder.setMaxCacheSizeOnLowDiskSpace(100);
builder.setMaxCacheSizeOnVeryLowDiskSpace(30 * ByteConstants.MB);
builder.setVersion(1);
builder.setBaseDirectoryName("imgcache");
builder.setBaseDirectoryPath(new File(FileUtils.getUserWorkingFolder()));
DiskCacheConfig diskCacheConfig = builder.build();
ImagePipelineConfig config = ImagePipelineConfig.newBuilder(this)
.setMainDiskCacheConfig(diskCacheConfig)
.build();
Fresco.initialize(this , config);

想知道这几个参数值表示的是什么意思,是怎么使用的。于是就查看了源码,发现这个参数初始化代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
private long mMaxCacheSize = 40 * ByteConstants.MB;
private long mMaxCacheSizeOnLowDiskSpace = 10 * ByteConstants.MB;
private long mMaxCacheSizeOnVeryLowDiskSpace = 2 * ByteConstants.MB;
public Builder setMaxCacheSize(long maxCacheSize) {
mMaxCacheSize = maxCacheSize;
return this;
}
public Builder setMaxCacheSizeOnLowDiskSpace(long maxCacheSizeOnLowDiskSpace) {
mMaxCacheSizeOnLowDiskSpace = maxCacheSizeOnLowDiskSpace;
return this;
}
public Builder setMaxCacheSizeOnVeryLowDiskSpace(long maxCacheSizeOnVeryLowDiskSpace) {
mMaxCacheSizeOnVeryLowDiskSpace = maxCacheSizeOnVeryLowDiskSpace;
return this;
}

看到这个代码就立马反应过来了,少了一个常量ByteConstants.MB?把项目中的初始化代码修改了一下,加上了这个常量,代码如下所示:

1
2
3
4
5
DiskCacheConfig.Builder builder = DiskCacheConfig.newBuilder(this);
builder.setMaxCacheSize(150 * ByteConstants.MB);
builder.setMaxCacheSizeOnLowDiskSpace(100 * ByteConstants.MB);
builder.setMaxCacheSizeOnVeryLowDiskSpace(30 * ByteConstants.MB);

再来测试时,发现问题解决了,不会出现保存失败的情况。v2.ols100.1这个目录下缓存了很多文件,文件大小一下子就几M了。

然后用上面代码中的关键字在google上搜索了一下,发现代码是copy过来的,参数值全部都一样。好吧,我认栽。

文章目录