onAssetsChanged method
Called when assets changed and obtained notifications from the OS. 系统发出资源变更的通知时调用的方法
Implementation
@override
Future<void> onAssetsChanged(MethodCall call, StateSetter setState) async {
final permission = permissionNotifier.value;
bool predicate() {
final path = provider.currentPath?.path;
if (assetsChangeRefreshPredicate != null) {
return assetsChangeRefreshPredicate!(permission, call, path);
}
return path?.isAll ?? true;
}
if (!predicate()) {
return;
}
assetsChangeCallback?.call(permission, call, provider.currentPath?.path);
final createIds = <String>[];
final updateIds = <String>[];
final deleteIds = <String>[];
int newCount = 0;
int oldCount = 0;
// Typically for iOS.
if (call.arguments case final Map arguments) {
if (arguments['newCount'] case final int count) {
newCount = count;
}
if (arguments['oldCount'] case final int count) {
oldCount = count;
}
for (final e in (arguments['create'] as List?) ?? []) {
if (e['id'] case final String id) {
createIds.add(id);
}
}
for (final e in (arguments['update'] as List?) ?? []) {
if (e['id'] case final String id) {
updateIds.add(id);
}
}
for (final e in (arguments['delete'] as List?) ?? []) {
if (e['id'] case final String id) {
deleteIds.add(id);
}
}
if (createIds.isEmpty &&
updateIds.isEmpty &&
deleteIds.isEmpty &&
// Updates with limited permission on iOS does not provide any IDs.
// Counting on length changes is not reliable.
(newCount == oldCount && permission != PermissionState.limited)) {
return;
}
}
// Throttle handling.
if (onAssetsChangedLock case final lock?) {
return lock.future;
}
final lock = Completer<void>();
onAssetsChangedLock = lock;
Future<void>(() async {
// Replace the updated assets if update only.
if (updateIds.isNotEmpty && createIds.isEmpty && deleteIds.isEmpty) {
await Future.wait(
updateIds.map((id) async {
final i = provider.currentAssets.indexWhere((e) => e.id == id);
if (i != -1) {
final asset =
await provider.currentAssets[i].obtainForNewProperties();
provider.currentAssets[i] = asset!;
}
}),
);
return;
}
await provider.getPaths(keepPreviousCount: true);
provider.currentPath = provider.paths.first;
final currentWrapper = provider.currentPath;
if (currentWrapper != null) {
final newPath = await currentWrapper.path.obtainForNewProperties();
final assetCount = await newPath.assetCountAsync;
final newPathWrapper = PathWrapper<AssetPathEntity>(
path: newPath,
assetCount: assetCount,
);
if (newPath.isAll) {
await provider.getAssetsFromCurrentPath();
final entitiesShouldBeRemoved = <AssetEntity>[];
for (final entity in provider.selectedAssets) {
if (!provider.currentAssets.contains(entity)) {
entitiesShouldBeRemoved.add(entity);
}
}
entitiesShouldBeRemoved.forEach(provider.selectedAssets.remove);
}
provider
..currentPath = newPathWrapper
..hasAssetsToDisplay = assetCount != 0
..isAssetsEmpty = assetCount == 0
..totalAssetsCount = assetCount
..getThumbnailFromPath(newPathWrapper);
}
isSwitchingPath.value = false;
}).then(lock.complete).catchError(lock.completeError).whenComplete(() {
onAssetsChangedLock = null;
});
}