Sfoglia il codice sorgente

Merge pull request #60 from CaiJingLong/photo-manager-0.4.0

photo manager to 0.4.0
version 0.4.0.
Use paging loading to optimize performance.
Caijinglong 5 anni fa
parent
commit
5faf5e8688
No account linked to committer's email address

+ 6
- 0
CHANGELOG.md Vedi File

@@ -1,5 +1,11 @@
1 1
 # CHANGELOG
2 2
 
3
+## 0.4.0
4
+
5
+roolback `photo_manager` to `0.4.0`
6
+
7
+- support androidQ.
8
+
3 9
 ## 0.3.4+1
4 10
 
5 11
 fix:

+ 21
- 26
example/lib/asset_image.dart Vedi File

@@ -22,34 +22,29 @@ class AssetImageWidget extends StatelessWidget {
22 22
     if (assetEntity == null) {
23 23
       return _buildContainer();
24 24
     }
25
-    return FutureBuilder<Size>(
26
-      builder: (c, s) {
27
-        if (!s.hasData) {
28
-          return Container();
25
+
26
+    print(
27
+        "assetEntity.width = ${assetEntity.width} , assetEntity.height = ${assetEntity.height}");
28
+
29
+    return FutureBuilder<Uint8List>(
30
+      builder: (BuildContext context, snapshot) {
31
+        if (snapshot.hasData) {
32
+          return _buildContainer(
33
+            child: Image.memory(
34
+              snapshot.data,
35
+              width: width,
36
+              height: height,
37
+              fit: boxFit,
38
+            ),
39
+          );
40
+        } else {
41
+          return _buildContainer();
29 42
         }
30
-        var size = s.data;
31
-        return FutureBuilder<Uint8List>(
32
-          builder: (BuildContext context, snapshot) {
33
-            if (snapshot.hasData) {
34
-              return _buildContainer(
35
-                child: Image.memory(
36
-                  snapshot.data,
37
-                  width: width,
38
-                  height: height,
39
-                  fit: boxFit,
40
-                ),
41
-              );
42
-            } else {
43
-              return _buildContainer();
44
-            }
45
-          },
46
-          future: assetEntity.thumbDataWithSize(
47
-            size.width.toInt(),
48
-            size.height.toInt(),
49
-          ),
50
-        );
51 43
       },
52
-      future: assetEntity.size,
44
+      future: assetEntity.thumbDataWithSize(
45
+        width.toInt(),
46
+        height.toInt(),
47
+      ),
53 48
     );
54 49
   }
55 50
 

+ 1
- 1
lib/src/engine/throttle.dart Vedi File

@@ -21,7 +21,7 @@ class Throttle {
21 21
     this.duration = const Duration(seconds: 2),
22 22
   });
23 23
 
24
-  void call() {
24
+  void call(call) {
25 25
     if (!_isRunning) {
26 26
       _startTimer();
27 27
       onCall?.call();

+ 60
- 0
lib/src/provider/asset_provider.dart Vedi File

@@ -0,0 +1,60 @@
1
+import 'dart:async';
2
+
3
+import 'package:photo_manager/photo_manager.dart';
4
+
5
+class AssetProvider {
6
+  Map<AssetPathEntity, AssetPaging> _dataMap = {};
7
+
8
+  AssetPathEntity _current;
9
+
10
+  AssetPathEntity get current => _current;
11
+
12
+  set current(AssetPathEntity current) {
13
+    _current = current;
14
+    if (_dataMap[current] == null) {
15
+      final paging = AssetPaging(current);
16
+      _dataMap[current] = paging;
17
+    }
18
+  }
19
+
20
+  List<AssetEntity> get data => _dataMap[current]?.data ?? [];
21
+
22
+  Future<void> loadMore() async {
23
+    final paging = getPaging();
24
+    if (paging != null) {
25
+      await paging.loadMore();
26
+    }
27
+  }
28
+
29
+  AssetPaging getPaging() => _dataMap[current];
30
+
31
+  bool get noMore => getPaging()?.noMore ?? false;
32
+
33
+  int get count => data?.length ?? 0;
34
+}
35
+
36
+class AssetPaging {
37
+  int page = 0;
38
+
39
+  List<AssetEntity> data = [];
40
+
41
+  final AssetPathEntity path;
42
+
43
+  final int pageCount;
44
+
45
+  bool noMore = false;
46
+
47
+  AssetPaging(this.path, {this.pageCount = 50});
48
+
49
+  Future<void> loadMore() async {
50
+    if (noMore == true) {
51
+      return;
52
+    }
53
+    var data = await path.getAssetListPaged(page, pageCount);
54
+    if (data.length == 0) {
55
+      noMore = true;
56
+    }
57
+    page++;
58
+    this.data.addAll(data);
59
+  }
60
+}

+ 9
- 4
lib/src/provider/config_provider.dart Vedi File

@@ -1,12 +1,14 @@
1 1
 import 'package:flutter/material.dart';
2 2
 import 'package:photo/src/entity/options.dart';
3
+import 'package:photo/src/provider/asset_provider.dart';
3 4
 import 'package:photo/src/provider/i18n_provider.dart';
4 5
 
5
-class ConfigProvider extends InheritedWidget {
6
+class PhotoPickerProvider extends InheritedWidget {
6 7
   final Options options;
7 8
   final I18nProvider provider;
9
+  final AssetProvider assetProvider = AssetProvider();
8 10
 
9
-  ConfigProvider({
11
+  PhotoPickerProvider({
10 12
     @required this.options,
11 13
     @required this.provider,
12 14
     @required Widget child,
@@ -18,6 +20,9 @@ class ConfigProvider extends InheritedWidget {
18 20
     return true;
19 21
   }
20 22
 
21
-  static ConfigProvider of(BuildContext context) =>
22
-      context.inheritFromWidgetOfExactType(ConfigProvider);
23
+  static PhotoPickerProvider of(BuildContext context) =>
24
+      context.inheritFromWidgetOfExactType(PhotoPickerProvider);
25
+
26
+  static AssetProvider assetProviderOf(BuildContext context) =>
27
+      of(context).assetProvider;
23 28
 }

+ 1
- 1
lib/src/ui/dialog/change_gallery_dialog.dart Vedi File

@@ -42,7 +42,7 @@ class _ChangeGalleryDialogState extends State<ChangeGalleryDialog> {
42 42
 
43 43
     return FlatButton(
44 44
       child: ListTile(
45
-        title: Text(text),
45
+        title: Text("$text (${entity.assetCount})"),
46 46
       ),
47 47
       onPressed: () {
48 48
         Navigator.pop(context, entity);

+ 8
- 17
lib/src/ui/page/main/image_item.dart Vedi File

@@ -54,23 +54,14 @@ class ImageItem extends StatelessWidget {
54 54
       height: double.infinity,
55 55
       fit: BoxFit.cover,
56 56
     );
57
-    // FutureBuilder()
58
-    var badge = FutureBuilder<Duration>(
59
-      future: entity.videoDuration,
60
-      builder: (ctx, snapshot) {
61
-        if (snapshot.hasData && snapshot != null) {
62
-          var buildBadge =
63
-              badgeDelegate?.buildBadge(context, entity.type, snapshot.data);
64
-          if (buildBadge == null) {
65
-            return Container();
66
-          } else {
67
-            return buildBadge;
68
-          }
69
-        } else {
70
-          return Container();
71
-        }
72
-      },
73
-    );
57
+    var badge;
58
+    final badgeBuilder =
59
+        badgeDelegate?.buildBadge(context, entity.type, entity.videoDuration);
60
+    if (badgeBuilder == null) {
61
+      badge = Container();
62
+    } else {
63
+      badge = badgeBuilder;
64
+    }
74 65
 
75 66
     return Stack(
76 67
       children: <Widget>[

+ 57
- 37
lib/src/ui/page/photo_main_page.dart Vedi File

@@ -7,6 +7,7 @@ import 'package:photo/src/delegate/loading_delegate.dart';
7 7
 import 'package:photo/src/engine/lru_cache.dart';
8 8
 import 'package:photo/src/engine/throttle.dart';
9 9
 import 'package:photo/src/entity/options.dart';
10
+import 'package:photo/src/provider/asset_provider.dart';
10 11
 import 'package:photo/src/provider/config_provider.dart';
11 12
 import 'package:photo/src/provider/gallery_list_provider.dart';
12 13
 import 'package:photo/src/provider/i18n_provider.dart';
@@ -38,13 +39,15 @@ class _PhotoMainPageState extends State<PhotoMainPage>
38 39
     with SelectedProvider, GalleryListProvider {
39 40
   Options get options => widget.options;
40 41
 
41
-  I18nProvider get i18nProvider => ConfigProvider.of(context).provider;
42
+  I18nProvider get i18nProvider => PhotoPickerProvider.of(context).provider;
43
+  AssetProvider get assetProvider =>
44
+      PhotoPickerProvider.of(context).assetProvider;
42 45
 
43
-  List<AssetEntity> list = [];
46
+  List<AssetEntity> get list => assetProvider.data;
44 47
 
45 48
   Color get themeColor => options.themeColor;
46 49
 
47
-  AssetPathEntity _currentPath = AssetPathEntity.all;
50
+  AssetPathEntity _currentPath;
48 51
 
49 52
   bool _isInit = false;
50 53
 
@@ -60,10 +63,10 @@ class _PhotoMainPageState extends State<PhotoMainPage>
60 63
   }
61 64
 
62 65
   String get currentGalleryName {
63
-    if (currentPath.isAll) {
66
+    if (currentPath?.isAll == true) {
64 67
       return i18nProvider.getAllGalleryText(options);
65 68
     }
66
-    return currentPath.name;
69
+    return currentPath?.name ?? "";
67 70
   }
68 71
 
69 72
   GlobalKey scaffoldKey;
@@ -227,12 +230,9 @@ class _PhotoMainPageState extends State<PhotoMainPage>
227 230
     galleryPathList.clear();
228 231
     galleryPathList.addAll(pathList);
229 232
 
230
-    List<AssetEntity> imageList;
231
-
232 233
     if (pathList.isNotEmpty) {
233
-      imageList = await pathList[0].assetList;
234
-      _sortAssetList(imageList);
235
-      _currentPath = pathList[0];
234
+      assetProvider.current = pathList[0];
235
+      await assetProvider.loadMore();
236 236
     }
237 237
 
238 238
     for (var path in pathList) {
@@ -241,10 +241,6 @@ class _PhotoMainPageState extends State<PhotoMainPage>
241 241
       }
242 242
     }
243 243
 
244
-    this.list.clear();
245
-    if (imageList != null) {
246
-      this.list.addAll(imageList);
247
-    }
248 244
     setState(() {
249 245
       _isInit = true;
250 246
     });
@@ -259,6 +255,10 @@ class _PhotoMainPageState extends State<PhotoMainPage>
259 255
       return _buildLoading();
260 256
     }
261 257
 
258
+    final noMore = assetProvider.noMore;
259
+
260
+    final count = assetProvider.count + (noMore ? 0 : 1);
261
+
262 262
     return Container(
263 263
       color: options.dividerColor,
264 264
       child: GridView.builder(
@@ -270,12 +270,18 @@ class _PhotoMainPageState extends State<PhotoMainPage>
270 270
           mainAxisSpacing: options.padding,
271 271
         ),
272 272
         itemBuilder: _buildItem,
273
-        itemCount: list.length,
273
+        itemCount: count,
274 274
       ),
275 275
     );
276 276
   }
277 277
 
278 278
   Widget _buildItem(BuildContext context, int index) {
279
+    final noMore = assetProvider.noMore;
280
+    if (!noMore && index == assetProvider.count) {
281
+      _loadMore();
282
+      return _buildLoading();
283
+    }
284
+
279 285
     var data = list[index];
280 286
     return RepaintBoundary(
281 287
       child: GestureDetector(
@@ -297,6 +303,11 @@ class _PhotoMainPageState extends State<PhotoMainPage>
297 303
     );
298 304
   }
299 305
 
306
+  _loadMore() async {
307
+    await assetProvider.loadMore();
308
+    setState(() {});
309
+  }
310
+
300 311
   _buildMask(bool showMask) {
301 312
     return IgnorePointer(
302 313
       child: AnimatedContainer(
@@ -364,17 +375,22 @@ class _PhotoMainPageState extends State<PhotoMainPage>
364 375
     setState(() {});
365 376
   }
366 377
 
367
-  void _onGalleryChange(AssetPathEntity assetPathEntity) {
368
-    _currentPath = assetPathEntity;
369
-
370
-    _currentPath.assetList.then((v) async {
371
-      _sortAssetList(v);
372
-      list.clear();
373
-      list.addAll(v);
374
-      scrollController.jumpTo(0.0);
375
-      await checkPickImageEntity();
378
+  void _onGalleryChange(AssetPathEntity assetPathEntity) async {
379
+    // _currentPath = assetPathEntity;
380
+
381
+    // _currentPath.assetList.then((v) async {
382
+    //   _sortAssetList(v);
383
+    //   list.clear();
384
+    //   list.addAll(v);
385
+    //   scrollController.jumpTo(0.0);
386
+    //   await checkPickImageEntity();
387
+    //   setState(() {});
388
+    // });
389
+    if (assetPathEntity != assetProvider.current) {
390
+      assetProvider.current = assetPathEntity;
391
+      await assetProvider.loadMore();
376 392
       setState(() {});
377
-    });
393
+    }
378 394
   }
379 395
 
380 396
   void _onItemClick(AssetEntity data, int index) {
@@ -383,8 +399,8 @@ class _PhotoMainPageState extends State<PhotoMainPage>
383 399
     Navigator.of(context).push(
384 400
       MaterialPageRoute(
385 401
         builder: (ctx) {
386
-          return ConfigProvider(
387
-            provider: ConfigProvider.of(context).provider,
402
+          return PhotoPickerProvider(
403
+            provider: PhotoPickerProvider.of(context).provider,
388 404
             options: options,
389 405
             child: PhotoPreviewPage(
390 406
               selectedProvider: this,
@@ -392,6 +408,8 @@ class _PhotoMainPageState extends State<PhotoMainPage>
392 408
               initIndex: index,
393 409
               changeProviderOnCheckChange: true,
394 410
               result: result,
411
+              isPreview: false,
412
+              assetProvider: assetProvider,
395 413
             ),
396 414
           );
397 415
         },
@@ -411,16 +429,18 @@ class _PhotoMainPageState extends State<PhotoMainPage>
411 429
     isPushed = true;
412 430
     var v = await Navigator.of(context).push(
413 431
       MaterialPageRoute(
414
-        builder: (ctx) => ConfigProvider(
415
-              provider: ConfigProvider.of(context).provider,
416
-              options: options,
417
-              child: PhotoPreviewPage(
418
-                selectedProvider: this,
419
-                list: List.of(selectedList),
420
-                changeProviderOnCheckChange: false,
421
-                result: result,
422
-              ),
423
-            ),
432
+        builder: (ctx) => PhotoPickerProvider(
433
+          provider: PhotoPickerProvider.of(context).provider,
434
+          options: options,
435
+          child: PhotoPreviewPage(
436
+            selectedProvider: this,
437
+            list: List.of(selectedList),
438
+            changeProviderOnCheckChange: false,
439
+            result: result,
440
+            isPreview: true,
441
+            assetProvider: assetProvider,
442
+          ),
443
+        ),
424 444
       ),
425 445
     );
426 446
     if (handlePreviewResult(v)) {

+ 55
- 24
lib/src/ui/page/photo_preview_page.dart Vedi File

@@ -3,6 +3,7 @@ import 'dart:typed_data';
3 3
 
4 4
 import 'package:flutter/material.dart';
5 5
 import 'package:photo/src/entity/options.dart';
6
+import 'package:photo/src/provider/asset_provider.dart';
6 7
 import 'package:photo/src/provider/config_provider.dart';
7 8
 import 'package:photo/src/provider/selected_provider.dart';
8 9
 import 'package:photo/src/ui/page/photo_main_page.dart';
@@ -18,16 +19,23 @@ class PhotoPreviewPage extends StatefulWidget {
18 19
   /// 这个参数是控制在内部点击check后是否实时修改provider状态
19 20
   final bool changeProviderOnCheckChange;
20 21
 
22
+  /// 是否通过预览进来的
23
+  final bool isPreview;
24
+
21 25
   /// 这里封装了结果
22 26
   final PhotoPreviewResult result;
23 27
 
28
+  final AssetProvider assetProvider;
29
+
24 30
   const PhotoPreviewPage({
25 31
     Key key,
26 32
     @required this.selectedProvider,
27 33
     @required this.list,
28 34
     @required this.changeProviderOnCheckChange,
29 35
     @required this.result,
36
+    @required this.assetProvider,
30 37
     this.initIndex = 0,
38
+    this.isPreview = false,
31 39
   }) : super(key: key);
32 40
 
33 41
   @override
@@ -35,7 +43,8 @@ class PhotoPreviewPage extends StatefulWidget {
35 43
 }
36 44
 
37 45
 class _PhotoPreviewPageState extends State<PhotoPreviewPage> {
38
-  ConfigProvider get config => ConfigProvider.of(context);
46
+  PhotoPickerProvider get config => PhotoPickerProvider.of(context);
47
+  AssetProvider get assetProvider => widget.assetProvider;
39 48
 
40 49
   Options get options => config.options;
41 50
 
@@ -45,7 +54,12 @@ class _PhotoPreviewPageState extends State<PhotoPreviewPage> {
45 54
 
46 55
   SelectedProvider get selectedProvider => widget.selectedProvider;
47 56
 
48
-  List<AssetEntity> get list => widget.list;
57
+  List<AssetEntity> get list {
58
+    if (!widget.isPreview) {
59
+      return assetProvider.data;
60
+    }
61
+    return widget.list;
62
+  }
49 63
 
50 64
   StreamController<int> pageChangeController = StreamController.broadcast();
51 65
 
@@ -96,6 +110,13 @@ class _PhotoPreviewPageState extends State<PhotoPreviewPage> {
96 110
 
97 111
   @override
98 112
   Widget build(BuildContext context) {
113
+    int totalCount = assetProvider.current.assetCount ?? 0;
114
+    if (!widget.isPreview) {
115
+      totalCount = assetProvider.current.assetCount;
116
+    } else {
117
+      totalCount = list.length;
118
+    }
119
+
99 120
     var data = Theme.of(context);
100 121
     var textStyle = TextStyle(
101 122
       color: options.textColor,
@@ -114,33 +135,35 @@ class _PhotoPreviewPageState extends State<PhotoPreviewPage> {
114 135
           title: StreamBuilder(
115 136
             stream: pageStream,
116 137
             initialData: widget.initIndex,
117
-            builder: (ctx, snap) => Text(
118
-                  "${snap.data + 1}/${widget.list.length}",
119
-                  style: TextStyle(
120
-                    color: options.textColor,
121
-                  ),
138
+            builder: (ctx, snap) {
139
+              return Text(
140
+                "${snap.data + 1}/$totalCount",
141
+                style: TextStyle(
142
+                  color: options.textColor,
122 143
                 ),
144
+              );
145
+            },
123 146
           ),
124 147
           actions: <Widget>[
125 148
             StreamBuilder(
126 149
               stream: pageStream,
127 150
               builder: (ctx, s) => FlatButton(
128
-                    splashColor: Colors.transparent,
129
-                    onPressed: selectedList.length == 0 ? null : sure,
130
-                    child: Text(
131
-                      config.provider.getSureText(options, selectedList.length),
132
-                      style: selectedList.length == 0
133
-                          ? textStyle.copyWith(color: options.disableColor)
134
-                          : textStyle,
135
-                    ),
136
-                  ),
151
+                splashColor: Colors.transparent,
152
+                onPressed: selectedList.length == 0 ? null : sure,
153
+                child: Text(
154
+                  config.provider.getSureText(options, selectedList.length),
155
+                  style: selectedList.length == 0
156
+                      ? textStyle.copyWith(color: options.disableColor)
157
+                      : textStyle,
158
+                ),
159
+              ),
137 160
             ),
138 161
           ],
139 162
         ),
140 163
         body: PageView.builder(
141 164
           controller: pageController,
142 165
           itemBuilder: _buildItem,
143
-          itemCount: list.length,
166
+          itemCount: totalCount,
144 167
           onPageChanged: _onPageChanged,
145 168
         ),
146 169
         bottomSheet: _buildThumb(),
@@ -244,6 +267,10 @@ class _PhotoPreviewPageState extends State<PhotoPreviewPage> {
244 267
   }
245 268
 
246 269
   Widget _buildItem(BuildContext context, int index) {
270
+    if (!widget.isPreview && index >= list.length - 5) {
271
+      _loadMore();
272
+    }
273
+
247 274
     var data = list[index];
248 275
     return BigPhotoImage(
249 276
       assetEntity: data,
@@ -251,6 +278,10 @@ class _PhotoPreviewPageState extends State<PhotoPreviewPage> {
251 278
     );
252 279
   }
253 280
 
281
+  Future<void> _loadMore() async {
282
+    assetProvider.loadMore();
283
+  }
284
+
254 285
   Widget _buildLoadingWidget(AssetEntity entity) {
255 286
     return options.loadingDelegate
256 287
         .buildBigImageLoading(context, entity, themeColor);
@@ -263,13 +294,13 @@ class _PhotoPreviewPageState extends State<PhotoPreviewPage> {
263 294
   Widget _buildThumb() {
264 295
     return StreamBuilder(
265 296
       builder: (ctx, snapshot) => Container(
266
-            height: 80.0,
267
-            child: ListView.builder(
268
-              itemBuilder: _buildThumbItem,
269
-              itemCount: previewList.length,
270
-              scrollDirection: Axis.horizontal,
271
-            ),
272
-          ),
297
+        height: 80.0,
298
+        child: ListView.builder(
299
+          itemBuilder: _buildThumbItem,
300
+          itemCount: previewList.length,
301
+          scrollDirection: Axis.horizontal,
302
+        ),
303
+      ),
273 304
       stream: pageStream,
274 305
     );
275 306
   }

+ 1
- 1
lib/src/ui/photo_app.dart Vedi File

@@ -20,7 +20,7 @@ class PhotoApp extends StatelessWidget {
20 20
 
21 21
   @override
22 22
   Widget build(BuildContext context) {
23
-    return ConfigProvider(
23
+    return PhotoPickerProvider(
24 24
       provider: provider,
25 25
       options: options,
26 26
       child: PhotoMainPage(

+ 7
- 7
pubspec.lock Vedi File

@@ -1,5 +1,5 @@
1 1
 # Generated by pub
2
-# See https://www.dartlang.org/tools/pub/glossary#lockfile
2
+# See https://dart.dev/tools/pub/glossary#lockfile
3 3
 packages:
4 4
   async:
5 5
     dependency: transitive
@@ -7,7 +7,7 @@ packages:
7 7
       name: async
8 8
       url: "https://pub.flutter-io.cn"
9 9
     source: hosted
10
-    version: "2.1.0"
10
+    version: "2.2.0"
11 11
   boolean_selector:
12 12
     dependency: transitive
13 13
     description:
@@ -66,21 +66,21 @@ packages:
66 66
       name: pedantic
67 67
       url: "https://pub.flutter-io.cn"
68 68
     source: hosted
69
-    version: "1.5.0"
69
+    version: "1.7.0"
70 70
   photo_manager:
71 71
     dependency: "direct main"
72 72
     description:
73 73
       name: photo_manager
74 74
       url: "https://pub.flutter-io.cn"
75 75
     source: hosted
76
-    version: "0.3.4"
76
+    version: "0.4.0"
77 77
   quiver:
78 78
     dependency: transitive
79 79
     description:
80 80
       name: quiver
81 81
       url: "https://pub.flutter-io.cn"
82 82
     source: hosted
83
-    version: "2.0.2"
83
+    version: "2.0.3"
84 84
   sky_engine:
85 85
     dependency: transitive
86 86
     description: flutter
@@ -127,7 +127,7 @@ packages:
127 127
       name: test_api
128 128
       url: "https://pub.flutter-io.cn"
129 129
     source: hosted
130
-    version: "0.2.4"
130
+    version: "0.2.5"
131 131
   typed_data:
132 132
     dependency: transitive
133 133
     description:
@@ -143,4 +143,4 @@ packages:
143 143
     source: hosted
144 144
     version: "2.0.8"
145 145
 sdks:
146
-  dart: ">=2.2.0 <3.0.0"
146
+  dart: ">=2.2.2 <3.0.0"

+ 3
- 3
pubspec.yaml Vedi File

@@ -1,6 +1,6 @@
1 1
 name: photo
2 2
 description: image picker, multi picker support video/icloud asset, use flutter as ui, if you want to build custom ui, you just use photo_manager.
3
-version: 0.3.4+1
3
+version: 0.4.0
4 4
 author: caijinglong<cjl_spy@163.com>
5 5
 homepage: https://github.com/CaiJingLong/flutter_photo
6 6
 
@@ -11,11 +11,11 @@ dependencies:
11 11
   flutter:
12 12
     sdk: flutter
13 13
 
14
-  photo_manager: ^0.3.4
14
+  photo_manager: ^0.4.0
15 15
   # photo_manager:
16 16
   #   git:
17 17
   #     url: https://github.com/CaiJingLong/flutter_photo_manager.git
18
-  #     ref: 2e4821c1fa797272e4c454366b4fb264e8a054d6
18
+  #     ref: ffaa6e8470708e63c3456837c8bd6eef7b0d42df
19 19
   # photo_manager:
20 20
   #   path: ../flutter_photo_manager
21 21