native call priority management
This commit is contained in:
parent
6a5603a116
commit
28e053cdd6
21 changed files with 135 additions and 53 deletions
|
@ -1,8 +1,8 @@
|
|||
import 'package:aves/model/image_entry.dart';
|
||||
import 'package:aves/model/image_file_service.dart';
|
||||
import 'package:aves/model/settings.dart';
|
||||
import 'package:aves/services/image_file_service.dart';
|
||||
import 'package:aves/services/viewer_service.dart';
|
||||
import 'package:aves/utils/android_file_utils.dart';
|
||||
import 'package:aves/utils/viewer_service.dart';
|
||||
import 'package:aves/widgets/album/collection_page.dart';
|
||||
import 'package:aves/widgets/common/data_providers/media_store_collection_provider.dart';
|
||||
import 'package:aves/widgets/fullscreen/fullscreen_page.dart';
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
import 'package:aves/model/favourite_repo.dart';
|
||||
import 'package:aves/model/image_file_service.dart';
|
||||
import 'package:aves/model/image_metadata.dart';
|
||||
import 'package:aves/model/metadata_service.dart';
|
||||
import 'package:aves/services/image_file_service.dart';
|
||||
import 'package:aves/services/metadata_service.dart';
|
||||
import 'package:aves/services/service_policy.dart';
|
||||
import 'package:aves/utils/change_notifier.dart';
|
||||
import 'package:aves/utils/time_utils.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
|
@ -220,7 +221,11 @@ class ImageEntry {
|
|||
|
||||
final coordinates = Coordinates(latitude, longitude);
|
||||
try {
|
||||
final addresses = await Geocoder.local.findAddressesFromCoordinates(coordinates);
|
||||
final addresses = await servicePolicy.call(
|
||||
() => Geocoder.local.findAddressesFromCoordinates(coordinates),
|
||||
ServiceCallPriority.background,
|
||||
'findAddressesFromCoordinates-$path',
|
||||
);
|
||||
if (addresses != null && addresses.isNotEmpty) {
|
||||
final address = addresses.first;
|
||||
addressDetails = AddressDetails(
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import 'dart:typed_data';
|
||||
|
||||
import 'package:aves/model/image_entry.dart';
|
||||
import 'package:aves/services/service_policy.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
|
||||
|
@ -42,21 +43,27 @@ class ImageFileService {
|
|||
return Uint8List(0);
|
||||
}
|
||||
|
||||
static Future<Uint8List> getThumbnail(ImageEntry entry, int width, int height) async {
|
||||
if (width > 0 && height > 0) {
|
||||
static Future<Uint8List> getThumbnail(ImageEntry entry, int width, int height) {
|
||||
return servicePolicy.call(
|
||||
() async {
|
||||
if (width > 0 && height > 0) {
|
||||
// debugPrint('getThumbnail width=$width path=${entry.path}');
|
||||
try {
|
||||
final result = await platform.invokeMethod('getThumbnail', <String, dynamic>{
|
||||
'entry': entry.toMap(),
|
||||
'width': width,
|
||||
'height': height,
|
||||
});
|
||||
return result as Uint8List;
|
||||
} on PlatformException catch (e) {
|
||||
debugPrint('getThumbnail failed with code=${e.code}, exception=${e.message}, details=${e.details}');
|
||||
}
|
||||
}
|
||||
return Uint8List(0);
|
||||
try {
|
||||
final result = await platform.invokeMethod('getThumbnail', <String, dynamic>{
|
||||
'entry': entry.toMap(),
|
||||
'width': width,
|
||||
'height': height,
|
||||
});
|
||||
return result as Uint8List;
|
||||
} on PlatformException catch (e) {
|
||||
debugPrint('getThumbnail failed with code=${e.code}, exception=${e.message}, details=${e.details}');
|
||||
}
|
||||
}
|
||||
return Uint8List(0);
|
||||
},
|
||||
ServiceCallPriority.asapLifo,
|
||||
'getThumbnail-${entry.path}',
|
||||
);
|
||||
}
|
||||
|
||||
static Future<void> cancelGetThumbnail(String uri) async {
|
|
@ -1,5 +1,6 @@
|
|||
import 'package:aves/model/image_entry.dart';
|
||||
import 'package:aves/model/image_metadata.dart';
|
||||
import 'package:aves/services/service_policy.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
|
||||
|
@ -26,26 +27,32 @@ class MetadataService {
|
|||
static Future<CatalogMetadata> getCatalogMetadata(ImageEntry entry) async {
|
||||
if (entry.isSvg) return null;
|
||||
|
||||
try {
|
||||
// return map with:
|
||||
// 'dateMillis': date taken in milliseconds since Epoch (long)
|
||||
// 'isAnimated': animated gif/webp (bool)
|
||||
// 'latitude': latitude (double)
|
||||
// 'longitude': longitude (double)
|
||||
// 'videoRotation': video rotation degrees (int)
|
||||
// 'xmpSubjects': ';' separated XMP subjects (string)
|
||||
// 'xmpTitleDescription': XMP title or XMP description (string)
|
||||
final result = await platform.invokeMethod('getCatalogMetadata', <String, dynamic>{
|
||||
'mimeType': entry.mimeType,
|
||||
'path': entry.path,
|
||||
'uri': entry.uri,
|
||||
}) as Map;
|
||||
result['contentId'] = entry.contentId;
|
||||
return CatalogMetadata.fromMap(result);
|
||||
} on PlatformException catch (e) {
|
||||
debugPrint('getCatalogMetadata failed with code=${e.code}, exception=${e.message}, details=${e.details}');
|
||||
}
|
||||
return null;
|
||||
return servicePolicy.call(
|
||||
() async {
|
||||
try {
|
||||
// return map with:
|
||||
// 'dateMillis': date taken in milliseconds since Epoch (long)
|
||||
// 'isAnimated': animated gif/webp (bool)
|
||||
// 'latitude': latitude (double)
|
||||
// 'longitude': longitude (double)
|
||||
// 'videoRotation': video rotation degrees (int)
|
||||
// 'xmpSubjects': ';' separated XMP subjects (string)
|
||||
// 'xmpTitleDescription': XMP title or XMP description (string)
|
||||
final result = await platform.invokeMethod('getCatalogMetadata', <String, dynamic>{
|
||||
'mimeType': entry.mimeType,
|
||||
'path': entry.path,
|
||||
'uri': entry.uri,
|
||||
}) as Map;
|
||||
result['contentId'] = entry.contentId;
|
||||
return CatalogMetadata.fromMap(result);
|
||||
} on PlatformException catch (e) {
|
||||
debugPrint('getCatalogMetadata failed with code=${e.code}, exception=${e.message}, details=${e.details}');
|
||||
}
|
||||
return null;
|
||||
},
|
||||
ServiceCallPriority.background,
|
||||
'getCatalogMetadata-${entry.path}',
|
||||
);
|
||||
}
|
||||
|
||||
static Future<OverlayMetadata> getOverlayMetadata(ImageEntry entry) async {
|
58
lib/services/service_policy.dart
Normal file
58
lib/services/service_policy.dart
Normal file
|
@ -0,0 +1,58 @@
|
|||
import 'dart:async';
|
||||
import 'dart:collection';
|
||||
|
||||
import 'package:flutter/cupertino.dart';
|
||||
|
||||
final ServicePolicy servicePolicy = ServicePolicy._private();
|
||||
|
||||
class ServicePolicy {
|
||||
final Queue<VoidCallback> _asapQueue = Queue(), _normalQueue = Queue(), _backgroundQueue = Queue();
|
||||
VoidCallback _running;
|
||||
|
||||
ServicePolicy._private();
|
||||
|
||||
Future<T> call<T>(Future<T> Function() platformCall, [ServiceCallPriority priority = ServiceCallPriority.normal, String debugLabel]) {
|
||||
Queue<VoidCallback> q;
|
||||
switch (priority) {
|
||||
case ServiceCallPriority.asapFifo:
|
||||
q = _asapQueue;
|
||||
break;
|
||||
case ServiceCallPriority.asapLifo:
|
||||
q = _asapQueue;
|
||||
break;
|
||||
case ServiceCallPriority.background:
|
||||
q = _backgroundQueue;
|
||||
break;
|
||||
case ServiceCallPriority.normal:
|
||||
default:
|
||||
q = _normalQueue;
|
||||
break;
|
||||
}
|
||||
final completer = Completer<T>();
|
||||
final wrapped = () async {
|
||||
// if (debugLabel != null) debugPrint('$runtimeType $debugLabel start');
|
||||
final result = await platformCall();
|
||||
completer.complete(result);
|
||||
// if (debugLabel != null) debugPrint('$runtimeType $debugLabel completed');
|
||||
_running = null;
|
||||
_pickNext();
|
||||
};
|
||||
if (priority == ServiceCallPriority.asapLifo) {
|
||||
q.addFirst(wrapped);
|
||||
} else {
|
||||
q.addLast(wrapped);
|
||||
}
|
||||
|
||||
_pickNext();
|
||||
return completer.future;
|
||||
}
|
||||
|
||||
void _pickNext() {
|
||||
if (_running != null) return;
|
||||
final queue = [_asapQueue, _normalQueue, _backgroundQueue].firstWhere((q) => q.isNotEmpty, orElse: () => null);
|
||||
_running = queue?.removeFirst();
|
||||
_running?.call();
|
||||
}
|
||||
}
|
||||
|
||||
enum ServiceCallPriority { asapFifo, asapLifo, normal, background }
|
|
@ -1,5 +1,5 @@
|
|||
import 'package:aves/utils/android_app_service.dart';
|
||||
import 'package:aves/utils/android_file_service.dart';
|
||||
import 'package:aves/services/android_app_service.dart';
|
||||
import 'package:aves/services/android_file_service.dart';
|
||||
import 'package:path/path.dart';
|
||||
|
||||
final AndroidFileUtils androidFileUtils = AndroidFileUtils._private();
|
||||
|
|
|
@ -4,6 +4,7 @@ import 'package:aves/model/collection_lens.dart';
|
|||
import 'package:aves/model/image_entry.dart';
|
||||
import 'package:aves/widgets/album/grid/header_generic.dart';
|
||||
import 'package:aves/widgets/album/grid/list_sliver.dart';
|
||||
import 'package:aves/widgets/album/grid/tile_extent_manager.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
|
@ -19,7 +20,7 @@ class SectionedListLayoutProvider extends StatelessWidget {
|
|||
@required this.scrollableWidth,
|
||||
@required this.tileExtent,
|
||||
@required this.child,
|
||||
}) : columnCount = (scrollableWidth / tileExtent).round();
|
||||
}) : columnCount = max((scrollableWidth / tileExtent).round(), TileExtentManager.columnCountMin);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
|
|
|
@ -7,8 +7,12 @@ class TileExtentManager {
|
|||
static const int columnCountMin = 2;
|
||||
static const int columnCountDefault = 4;
|
||||
static const double tileExtentMin = 46.0;
|
||||
static const screenDimensionMin = tileExtentMin * columnCountMin;
|
||||
|
||||
static double applyTileExtent(Size mqSize, double mqHorizontalPadding, ValueNotifier<double> extentNotifier, {double newExtent}) {
|
||||
// sanitize screen size (useful when reloading while screen is off, reporting a 0,0 size)
|
||||
mqSize = Size(max(mqSize.width, screenDimensionMin), max(mqSize.height, screenDimensionMin));
|
||||
|
||||
final availableWidth = mqSize.width - mqHorizontalPadding;
|
||||
var numColumns;
|
||||
if ((newExtent ?? 0) == 0) {
|
||||
|
|
|
@ -4,9 +4,9 @@ import 'package:aves/model/collection_lens.dart';
|
|||
import 'package:aves/model/collection_source.dart';
|
||||
import 'package:aves/model/favourite_repo.dart';
|
||||
import 'package:aves/model/image_entry.dart';
|
||||
import 'package:aves/model/image_file_service.dart';
|
||||
import 'package:aves/model/metadata_db.dart';
|
||||
import 'package:aves/model/settings.dart';
|
||||
import 'package:aves/services/image_file_service.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_native_timezone/flutter_native_timezone.dart';
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import 'dart:ui' as ui show Codec;
|
||||
|
||||
import 'package:aves/utils/android_app_service.dart';
|
||||
import 'package:aves/services/android_app_service.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import 'dart:ui' as ui show Codec;
|
||||
|
||||
import 'package:aves/model/image_entry.dart';
|
||||
import 'package:aves/model/image_file_service.dart';
|
||||
import 'package:aves/services/image_file_service.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import 'dart:ui' as ui show Codec;
|
||||
|
||||
import 'package:aves/model/image_file_service.dart';
|
||||
import 'package:aves/services/image_file_service.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import 'package:aves/model/image_file_service.dart';
|
||||
import 'package:aves/services/image_file_service.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_svg/flutter_svg.dart';
|
||||
|
|
|
@ -2,8 +2,8 @@ import 'dart:io';
|
|||
|
||||
import 'package:aves/model/collection_lens.dart';
|
||||
import 'package:aves/model/image_entry.dart';
|
||||
import 'package:aves/model/image_file_service.dart';
|
||||
import 'package:aves/utils/android_app_service.dart';
|
||||
import 'package:aves/services/android_app_service.dart';
|
||||
import 'package:aves/services/image_file_service.dart';
|
||||
import 'package:aves/widgets/common/image_providers/uri_image_provider.dart';
|
||||
import 'package:aves/widgets/fullscreen/debug.dart';
|
||||
import 'package:aves/widgets/fullscreen/fullscreen_actions.dart';
|
||||
|
|
|
@ -2,7 +2,7 @@ import 'package:aves/model/collection_lens.dart';
|
|||
import 'package:aves/model/filters/location.dart';
|
||||
import 'package:aves/model/image_entry.dart';
|
||||
import 'package:aves/model/settings.dart';
|
||||
import 'package:aves/utils/android_app_service.dart';
|
||||
import 'package:aves/services/android_app_service.dart';
|
||||
import 'package:aves/utils/geo_utils.dart';
|
||||
import 'package:aves/widgets/common/aves_filter_chip.dart';
|
||||
import 'package:aves/widgets/common/icons.dart';
|
||||
|
|
|
@ -2,7 +2,7 @@ import 'dart:async';
|
|||
import 'dart:collection';
|
||||
|
||||
import 'package:aves/model/image_entry.dart';
|
||||
import 'package:aves/model/metadata_service.dart';
|
||||
import 'package:aves/services/metadata_service.dart';
|
||||
import 'package:aves/utils/color_utils.dart';
|
||||
import 'package:aves/widgets/common/fx/highlight_decoration.dart';
|
||||
import 'package:aves/widgets/fullscreen/info/info_page.dart';
|
||||
|
|
|
@ -3,7 +3,7 @@ import 'dart:ui';
|
|||
|
||||
import 'package:aves/model/image_entry.dart';
|
||||
import 'package:aves/model/image_metadata.dart';
|
||||
import 'package:aves/model/metadata_service.dart';
|
||||
import 'package:aves/services/metadata_service.dart';
|
||||
import 'package:aves/utils/constants.dart';
|
||||
import 'package:aves/utils/geo_utils.dart';
|
||||
import 'package:aves/widgets/common/fx/blurred.dart';
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import 'package:aves/model/image_entry.dart';
|
||||
import 'package:aves/utils/android_app_service.dart';
|
||||
import 'package:aves/services/android_app_service.dart';
|
||||
import 'package:aves/utils/time_utils.dart';
|
||||
import 'package:aves/widgets/common/fx/blurred.dart';
|
||||
import 'package:aves/widgets/fullscreen/overlay/common.dart';
|
||||
|
|
Loading…
Reference in a new issue