第1节:Flutter源码查找

[TOC]

前言

2、flutter external声明方法的源码查找

image-20230916193216119

图片2

image-20230916193753386

image-20230916194301820

image-20230916194442691

2、_network_image_io.dart

~/.pub-cache/hosted/pub.flutter-io.cn/extended_image_library-3.4.2/lib/src/_network_image_io.dart

其主要方法如下:

1、loadBuffer方法用于加载图片数据并返回ImageStreamCompleter对象。

2、_loadAsync方法是实际加载图片数据的核心逻辑。它首先尝试从缓存中加载图片数据,如果缓存中不存在,则从网络加载图片数据。

3、_loadCache方法用于从缓存中加载图片数据。

4、_loadNetwork方法用于从网络加载图片数据。

5、getNetworkImageData方法用于从缓存或网络获取图片数据。

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
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
/// loadBuffer方法用于加载图片数据并返回ImageStreamCompleter对象。
@override
ImageStreamCompleter loadBuffer(
image_provider.ExtendedNetworkImageProvider key,
DecoderBufferCallback decode) {
// Ownership of this controller is handed off to [_loadAsync]; it is that
// method's responsibility to close the controller's stream when the image
// has been loaded or an error is thrown.
final StreamController<ImageChunkEvent> chunkEvents =
StreamController<ImageChunkEvent>();

return MultiFrameImageStreamCompleter(
codec: _loadAsync(
key as ExtendedNetworkImageProvider,
chunkEvents,
decode,
),
scale: key.scale,
chunkEvents: chunkEvents.stream,
debugLabel: key.url,
informationCollector: () {
return <DiagnosticsNode>[
DiagnosticsProperty<ImageProvider>('Image provider', this),
DiagnosticsProperty<image_provider.ExtendedNetworkImageProvider>(
'Image key', key),
];
},
);
}

/// _loadAsync方法是实际加载图片数据的核心逻辑。它首先尝试从缓存中加载图片数据,如果缓存中不存在,则从网络加载图片数据。
Future<ui.Codec> _loadAsync(
ExtendedNetworkImageProvider key,
StreamController<ImageChunkEvent> chunkEvents,
DecoderBufferCallback decode,
) async {
assert(key == this);
final String md5Key = cacheKey ?? keyToMd5(key.url);
ui.Codec? result;
if (cache) {
try {
final Uint8List? data = await _loadCache( /// _loadCache方法用于从缓存中加载图片数据。
key,
chunkEvents,
md5Key,
);
if (data != null) {
result = await instantiateImageCodec(data, decode);
}
} catch (e) {
if (printError) {
print(e);
}
}
}

if (result == null) {
try {
final Uint8List? data = await _loadNetwork(
key,
chunkEvents,
);
if (data != null) {
result = await instantiateImageCodec(data, decode);
}
} catch (e) {
if (printError) {
print(e);
}
}
}

//Failed to load
if (result == null) {
//result = await ui.instantiateImageCodec(kTransparentImage);
return Future<ui.Codec>.error(StateError('Failed to load $url.'));
}

return result;
}

/// _loadCache方法用于从缓存中加载图片数据。
/// Get the image from cache folder.
Future<Uint8List?> _loadCache(
ExtendedNetworkImageProvider key,
StreamController<ImageChunkEvent>? chunkEvents,
String md5Key,
) async {
final Directory _cacheImagesDirectory = Directory(
join((await getTemporaryDirectory()).path, cacheImageFolderName));
Uint8List? data;
// exist, try to find cache image file
if (_cacheImagesDirectory.existsSync()) { /// existsSync是一个同步方法,用于检查具有该路径的文件系统实体是否存在。
final File cacheFlie = File(join(_cacheImagesDirectory.path, md5Key));
if (cacheFlie.existsSync()) { /// existsSync是一个同步方法,用于检查具有该路径的文件系统实体是否存在。
if (key.cacheMaxAge != null) {
final DateTime now = DateTime.now();
final FileStat fs = cacheFlie.statSync();
if (now.subtract(key.cacheMaxAge!).isAfter(fs.changed)) {
cacheFlie.deleteSync(recursive: true);
} else {
data = await cacheFlie.readAsBytes();
}
} else {
data = await cacheFlie.readAsBytes();
}
}
}
// create folder
else {
await _cacheImagesDirectory.create();
}
// load from network
if (data == null) {
data = await _loadNetwork(
key,
chunkEvents,
);
if (data != null) {
// cache image file
await File(join(_cacheImagesDirectory.path, md5Key)).writeAsBytes(data);
}
}

return data;
}

existsSync() 方法是 dart:io 包中的一个方法,用于检查文件系统实体是否存在。

问:existsSync() 会有性能问题吗

existsSync() 方法是一个同步方法,它会阻塞当前线程,直到文件系统中的实体存在与否得到确认。在使用 existsSync() 方法时,如果要检查的文件系统实体数量较少,并且操作的频率不高,一般不会引起明显的性能问题。

然而,如果你需要频繁地调用 existsSync() 方法,或者需要检查大量的文件系统实体,那么它可能会对性能产生一定的影响。这是因为每次调用 existsSync() 都需要同步地与文件系统进行交互,这可能会导致线程阻塞、IO操作和文件系统访问开销增加。

如果你关注性能问题,建议考虑使用异步的方式来检查文件系统实体的存在性,例如使用 exists() 方法,它返回一个 Future<bool>,可以非阻塞地进行文件系统查询。异步方式可以提高并发性和响应性,并且在处理大量文件系统实体时具有更好的性能表现。

另外,如果你需要频繁地监视文件系统中的实体变化,例如文件的创建、修改或删除,可以考虑使用文件系统监听器(File System Watcher)来异步地接收文件系统事件通知,而不是反复地调用 existsSync() 方法。

总结起来,如果使用恰当并避免频繁调用,existsSync() 方法不会引起严重的性能问题。但在需要高性能和并发性的场景下,异步方式可能更为合适。

image-20230916201242976