Skip to content

Commit 5997d05

Browse files
authored
✨ Introduce PathWrapper (#338)
1 parent 6430803 commit 5997d05

14 files changed

+468
-306
lines changed

CHANGELOG.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,14 @@ that can be found in the LICENSE file. -->
44

55
# Changelog
66

7+
## 8.0.0-dev.1
8+
9+
To know more about breaking changes, see [Migration Guide][].
10+
11+
### Improvements
12+
13+
- Introduce `PathWrapper` to improve the overall loading speed. (#338)
14+
715
## 7.3.2
816

917
### Improvements

analysis_options.yaml

Lines changed: 30 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,8 @@ analyzer:
2929

3030
linter:
3131
rules:
32-
# This list is derived from the list of all available lints located at
32+
# these rules are documented on and in the same order as
33+
# the Dart Lint rules page to make maintenance easier
3334
# https://github.com/dart-lang/linter/blob/master/example/all.yaml
3435
- always_declare_return_types
3536
- always_put_control_body_on_new_line
@@ -40,34 +41,32 @@ linter:
4041
- annotate_overrides
4142
# - avoid_annotating_with_dynamic # conflicts with always_specify_types
4243
- avoid_bool_literals_in_conditional_expressions
43-
# - avoid_catches_without_on_clauses # blocked on https://github.com/dart-lang/linter/issues/3023
44-
# - avoid_catching_errors # blocked on https://github.com/dart-lang/linter/issues/3023
44+
# - avoid_catches_without_on_clauses # we do this commonly
45+
# - avoid_catching_errors # we do this commonly
4546
- avoid_classes_with_only_static_members
46-
- avoid_double_and_int_checks
47+
# - avoid_double_and_int_checks # only useful when targeting JS runtime
4748
- avoid_dynamic_calls
4849
- avoid_empty_else
4950
- avoid_equals_and_hash_code_on_mutable_classes
5051
- avoid_escaping_inner_quotes
5152
- avoid_field_initializers_in_const_classes
52-
# - avoid_final_parameters # incompatible with prefer_final_parameters
5353
- avoid_function_literals_in_foreach_calls
54-
- avoid_implementing_value_types
54+
# - avoid_implementing_value_types # not yet tested
5555
- avoid_init_to_null
56-
- avoid_js_rounded_ints
57-
# - avoid_multiple_declarations_per_line # seems to be a stylistic choice we don't subscribe to
56+
# - avoid_js_rounded_ints # only useful when targeting JS runtime
5857
- avoid_null_checks_in_equality_operators
59-
# - avoid_positional_boolean_parameters # would have been nice to enable this but by now there's too many places that break it
60-
- avoid_print
58+
# - avoid_positional_boolean_parameters # not yet tested
59+
# - avoid_print # not yet tested
6160
# - avoid_private_typedef_functions # we prefer having typedef (discussion in https://github.com/flutter/flutter/pull/16356)
6261
- avoid_redundant_argument_values
6362
- avoid_relative_lib_imports
6463
- avoid_renaming_method_parameters
6564
- avoid_return_types_on_setters
66-
# - avoid_returning_null # still violated by some pre-nnbd code that we haven't yet migrated
67-
- avoid_returning_null_for_future
65+
# - avoid_returning_null # there are plenty of valid reasons to return null
66+
# - avoid_returning_null_for_future # not yet tested
6867
- avoid_returning_null_for_void
69-
# - avoid_returning_this # there are enough valid reasons to return `this` that this lint ends up with too many false positives
70-
- avoid_setters_without_getters
68+
# - avoid_returning_this # there are plenty of valid reasons to return this
69+
# - avoid_setters_without_getters # not yet tested
7170
- avoid_shadowing_type_parameters
7271
- avoid_single_cascade_in_expression_statements
7372
- avoid_slow_async_io
@@ -77,28 +76,24 @@ linter:
7776
- avoid_unnecessary_containers
7877
- avoid_unused_constructor_parameters
7978
- avoid_void_async
80-
# - avoid_web_libraries_in_flutter # we use web libraries in web-specific code, and our tests prevent us from using them elsewhere
79+
# - avoid_web_libraries_in_flutter # not yet tested
8180
- await_only_futures
8281
- camel_case_extensions
8382
- camel_case_types
8483
- cancel_subscriptions
85-
# - cascade_invocations # doesn't match the typical style of this repo
86-
- cast_nullable_to_non_nullable
84+
# - cascade_invocations # not yet tested
8785
# - close_sinks # not reliable enough
8886
# - comment_references # blocked on https://github.com/dart-lang/linter/issues/1142
89-
# - conditional_uri_does_not_exist # not yet tested
9087
# - constant_identifier_names # needs an opt-out https://github.com/dart-lang/linter/issues/204
9188
- control_flow_in_finally
9289
# - curly_braces_in_flow_control_structures # not required by flutter style
93-
- depend_on_referenced_packages
9490
- deprecated_consistency
95-
# - diagnostic_describe_all_properties # enabled only at the framework level (packages/flutter/lib)
91+
# - diagnostic_describe_all_properties # not yet tested
9692
- directives_ordering
97-
# - do_not_use_environment # there are appropriate times to use the environment, especially in our tests and build logic
93+
# - do_not_use_environment # we do this commonly
9894
- empty_catches
9995
- empty_constructor_bodies
10096
- empty_statements
101-
- eol_at_end_of_file
10297
- exhaustive_cases
10398
- file_names
10499
- flutter_style_todos
@@ -110,25 +105,22 @@ linter:
110105
- leading_newlines_in_multiline_strings
111106
- library_names
112107
- library_prefixes
113-
- library_private_types_in_public_api
114108
# - lines_longer_than_80_chars # not required by flutter style
115109
- list_remove_unrelated_type
116-
# - literal_only_boolean_expressions # too many false positives: https://github.com/dart-lang/linter/issues/453
110+
# - literal_only_boolean_expressions # too many false positives: https://github.com/dart-lang/sdk/issues/34181
117111
- missing_whitespace_between_adjacent_strings
118112
- no_adjacent_strings_in_list
119-
- no_default_cases
113+
# - no_default_cases # too many false positives
120114
- no_duplicate_case_values
121-
- no_leading_underscores_for_library_prefixes
122-
- no_leading_underscores_for_local_identifiers
123115
- no_logic_in_create_state
124116
# - no_runtimeType_toString # ok in tests; we enable this only in packages/
125-
- non_constant_identifier_names
126117
- noop_primitive_operations
118+
- non_constant_identifier_names
127119
- null_check_on_nullable_type_parameter
128120
- null_closures
129121
# - omit_local_variable_types # opposite of always_specify_types
130122
# - one_member_abstracts # too many false positives
131-
- only_throw_errors # this does get disabled in a few places where we have legacy code that uses strings et al
123+
# - only_throw_errors # https://github.com/flutter/flutter/issues/5792
132124
- overridden_fields
133125
- package_api_docs
134126
- package_names
@@ -151,7 +143,6 @@ linter:
151143
- prefer_final_fields
152144
- prefer_final_in_for_each
153145
- prefer_final_locals
154-
# - prefer_final_parameters # we should enable this one day when it can be auto-fixed (https://github.com/dart-lang/linter/issues/3104), see also parameter_assignments
155146
- prefer_for_elements_to_map_fromIterable
156147
- prefer_foreach
157148
- prefer_function_declarations_over_variables
@@ -166,23 +157,20 @@ linter:
166157
- prefer_is_not_empty
167158
- prefer_is_not_operator
168159
- prefer_iterable_whereType
169-
# - prefer_mixin # Has false positives, see https://github.com/dart-lang/linter/issues/3018
170-
# - prefer_null_aware_method_calls # "call()" is confusing to people new to the language since it's not documented anywhere
160+
# - prefer_mixin # https://github.com/dart-lang/language/issues/32
171161
- prefer_null_aware_operators
172-
- prefer_relative_imports
162+
# - prefer_relative_imports # incompatible with sub-package imports
173163
- prefer_single_quotes
174164
- prefer_spread_collections
175165
- prefer_typing_uninitialized_variables
176166
- prefer_void_to_null
177167
- provide_deprecation_message
178168
# - public_member_api_docs # enabled on a case-by-case basis; see e.g. packages/analysis_options.yaml
179169
- recursive_getters
180-
# - require_trailing_commas # blocked on https://github.com/dart-lang/sdk/issues/47441
181-
- secure_pubspec_urls
170+
- require_trailing_commas
182171
- sized_box_for_whitespace
183-
# - sized_box_shrink_expand # not yet tested
184172
- slash_for_doc_comments
185-
- sort_child_properties_last
173+
# - sort_child_properties_last # not yet tested
186174
- sort_constructors_first
187175
# - sort_pub_dependencies # prevents separating pinned transitive dependencies
188176
- sort_unnamed_constructors_first
@@ -191,45 +179,38 @@ linter:
191179
- tighten_type_of_initializing_formals
192180
# - type_annotate_public_apis # subset of always_specify_types
193181
- type_init_formals
194-
# - unawaited_futures # too many false positives, especially with the way AnimationController works
182+
# - unawaited_futures # too many false positives
195183
- unnecessary_await_in_return
196184
- unnecessary_brace_in_string_interps
197185
- unnecessary_const
198-
- unnecessary_constructor_name
199186
# - unnecessary_final # conflicts with prefer_final_locals
200187
- unnecessary_getters_setters
201188
# - unnecessary_lambdas # has false positives: https://github.com/dart-lang/linter/issues/498
202-
- unnecessary_late
203189
- unnecessary_new
204190
- unnecessary_null_aware_assignments
205191
- unnecessary_null_checks
206192
- unnecessary_null_in_if_null_operators
207193
- unnecessary_nullable_for_final_variable_declarations
208194
- unnecessary_overrides
209195
- unnecessary_parenthesis
210-
# - unnecessary_raw_strings # what's "necessary" is a matter of opinion; consistency across strings can help readability more than this lint
196+
# - unnecessary_raw_strings # not yet tested
211197
- unnecessary_statements
212198
- unnecessary_string_escapes
213199
- unnecessary_string_interpolations
214200
- unnecessary_this
215201
- unrelated_type_equality_checks
216-
- unsafe_html
217-
# - use_build_context_synchronously
218-
# - use_colored_box # not yet tested
219-
# - use_decorated_box # not yet tested
220-
# - use_enums # not yet tested
202+
# - unsafe_html # not yet tested
221203
- use_full_hex_values_for_flutter_colors
222204
- use_function_type_syntax_for_parameters
223-
- use_if_null_to_convert_nulls_to_bools
205+
# - use_if_null_to_convert_nulls_to_bools # not yet tested
224206
- use_is_even_rather_than_modulo
225207
- use_key_in_widget_constructors
226208
- use_late_for_private_fields_and_variables
227209
- use_named_constants
228210
- use_raw_strings
229211
- use_rethrow_when_possible
230-
- use_setters_to_change_properties
212+
# - use_setters_to_change_properties # not yet tested
231213
# - use_string_buffers # has false positives: https://github.com/dart-lang/sdk/issues/34182
232-
- use_super_parameters
233214
- use_test_throws_matchers
234215
# - use_to_and_as_if_applicable # has false positives, so we prefer to catch this by code-review
235216
- valid_regexps

example/lib/constants/picker_method.dart

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -164,9 +164,12 @@ class PickMethod {
164164
final DefaultAssetPickerBuilderDelegate builder =
165165
picker.builder as DefaultAssetPickerBuilderDelegate;
166166
final DefaultAssetPickerProvider p = builder.provider;
167-
p.currentPath =
168-
await p.currentPath!.obtainForNewProperties();
169-
await p.switchPath(p.currentPath);
167+
await p.switchPath(
168+
PathWrapper<AssetPathEntity>(
169+
path:
170+
await p.currentPath!.path.obtainForNewProperties(),
171+
),
172+
);
170173
p.selectAsset(result);
171174
},
172175
child: const Center(

example/lib/customs/pickers/directory_file_asset_picker.dart

Lines changed: 32 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -295,19 +295,24 @@ class FileAssetPickerProvider extends AssetPickerProvider<File, Directory> {
295295
}) : super(selectedAssets: selectedAssets) {
296296
Future<void>.delayed(const Duration(milliseconds: 300), () async {
297297
await getPaths();
298-
getAssetsFromPath(0, pathsList.keys.elementAt(0));
298+
getAssetsFromPath(0, paths.first.path);
299299
});
300300
}
301301

302302
@override
303303
Future<void> getPaths() async {
304304
currentAssets = <File>[];
305-
pathsList.clear();
305+
paths.clear();
306306
final Directory? directory = await getExternalStorageDirectory();
307307
if (directory != null) {
308-
pathsList[directory] = null;
309-
currentPath = directory;
310-
pathsList[directory] = await getThumbnailFromPath(directory);
308+
final PathWrapper<Directory> wrapper = PathWrapper<Directory>(
309+
path: directory,
310+
thumbnailData: await getThumbnailFromPath(
311+
PathWrapper<Directory>(path: directory),
312+
),
313+
);
314+
paths.add(wrapper);
315+
currentPath = wrapper;
311316
}
312317
}
313318

@@ -327,9 +332,9 @@ class FileAssetPickerProvider extends AssetPickerProvider<File, Directory> {
327332
}
328333

329334
@override
330-
Future<Uint8List?> getThumbnailFromPath(Directory path) async {
335+
Future<Uint8List?> getThumbnailFromPath(PathWrapper<Directory> path) async {
331336
final List<FileSystemEntity> entities =
332-
path.listSync().whereType<File>().toList();
337+
path.path.listSync().whereType<File>().toList();
333338
currentAssets.clear();
334339
for (final FileSystemEntity entity in entities) {
335340
final String extension = basename(entity.path).split('.').last;
@@ -354,14 +359,14 @@ class FileAssetPickerProvider extends AssetPickerProvider<File, Directory> {
354359
}
355360

356361
@override
357-
Future<void> switchPath([Directory? path]) async {
362+
Future<void> switchPath([PathWrapper<Directory>? path]) async {
358363
if (path == null) {
359364
return;
360365
}
361366
currentPath = path;
362367
totalAssetsCount = 0;
363368
notifyListeners();
364-
await getAssetsFromPath(0, currentPath!);
369+
await getAssetsFromPath(0, currentPath!.path);
365370
}
366371
}
367372

@@ -839,15 +844,15 @@ class FileAssetPickerBuilder
839844
),
840845
),
841846
),
842-
child: Selector<FileAssetPickerProvider, Map<Directory, Uint8List?>>(
843-
selector: (_, FileAssetPickerProvider p) => p.pathsList,
844-
builder: (_, Map<Directory, Uint8List?> pathEntityList, __) {
847+
child: Selector<FileAssetPickerProvider, List<PathWrapper<Directory>>>(
848+
selector: (_, FileAssetPickerProvider p) => p.paths,
849+
builder: (_, List<PathWrapper<Directory>> paths, __) {
845850
return ListView.separated(
846851
padding: const EdgeInsetsDirectional.only(top: 1.0),
847-
itemCount: pathEntityList.length,
852+
itemCount: paths.length,
848853
itemBuilder: (_, int index) => pathEntityWidget(
849854
context: context,
850-
list: pathEntityList,
855+
list: paths,
851856
index: index,
852857
),
853858
separatorBuilder: (_, __) => Container(
@@ -877,15 +882,15 @@ class FileAssetPickerBuilder
877882
child: Row(
878883
mainAxisSize: MainAxisSize.min,
879884
children: <Widget>[
880-
Selector<FileAssetPickerProvider, Directory?>(
885+
Selector<FileAssetPickerProvider, PathWrapper<Directory>?>(
881886
selector: (_, FileAssetPickerProvider p) => p.currentPath,
882-
builder: (_, Directory? currentPathEntity, __) {
883-
if (currentPathEntity == null) {
887+
builder: (_, PathWrapper<Directory>? currentWrapper, __) {
888+
if (currentWrapper == null) {
884889
return const SizedBox.shrink();
885890
}
886891
return Flexible(
887892
child: Text(
888-
provider.currentPath!.path,
893+
currentWrapper.path.path,
889894
style: const TextStyle(
890895
fontSize: 18.0,
891896
fontWeight: FontWeight.normal,
@@ -929,12 +934,13 @@ class FileAssetPickerBuilder
929934
@override
930935
Widget pathEntityWidget({
931936
required BuildContext context,
932-
required Map<Directory, Uint8List?> list,
937+
required List<PathWrapper<Directory>> list,
933938
required int index,
934939
bool isAudio = false,
935940
}) {
936-
final Directory path = list.keys.elementAt(index);
937-
final Uint8List? data = list.values.elementAt(index);
941+
final PathWrapper<Directory> wrapper = list[index];
942+
final Directory path = wrapper.path;
943+
final Uint8List? data = wrapper.thumbnailData;
938944

939945
Widget builder() {
940946
if (data != null) {
@@ -951,7 +957,7 @@ class FileAssetPickerBuilder
951957
child: InkWell(
952958
splashFactory: InkSplash.splashFactory,
953959
onTap: () {
954-
provider.switchPath(path);
960+
provider.switchPath(wrapper);
955961
isSwitchingPath.value = false;
956962
},
957963
child: SizedBox(
@@ -978,17 +984,16 @@ class FileAssetPickerBuilder
978984
),
979985
),
980986
),
981-
Selector<FileAssetPickerProvider, Directory>(
987+
Selector<FileAssetPickerProvider, PathWrapper<Directory>>(
982988
selector: (_, FileAssetPickerProvider p) => p.currentPath!,
983-
builder: (_, Directory currentPathEntity, __) {
984-
if (currentPathEntity == path) {
989+
builder: (_, PathWrapper<Directory> currentPathEntity, __) {
990+
if (currentPathEntity == wrapper) {
985991
return const AspectRatio(
986992
aspectRatio: 1.0,
987993
child: Icon(Icons.check, color: themeColor, size: 26.0),
988994
);
989-
} else {
990-
return const SizedBox.shrink();
991995
}
996+
return const SizedBox.shrink();
992997
},
993998
),
994999
],

0 commit comments

Comments
 (0)