From e949733f2ac36ca6ba956262a3aeb018f2018e27 Mon Sep 17 00:00:00 2001 From: Maximilian Fischer Date: Fri, 25 Sep 2020 21:03:15 +0200 Subject: [PATCH 1/4] LiveList: added preloadedColumns --- .../dart/lib/src/utils/parse_live_list.dart | 56 +++++++++++-------- .../lib/src/utils/parse_live_list.dart | 28 +++++++--- 2 files changed, 54 insertions(+), 30 deletions(-) diff --git a/packages/dart/lib/src/utils/parse_live_list.dart b/packages/dart/lib/src/utils/parse_live_list.dart index db4e3a1cc..63822205b 100644 --- a/packages/dart/lib/src/utils/parse_live_list.dart +++ b/packages/dart/lib/src/utils/parse_live_list.dart @@ -2,7 +2,9 @@ part of flutter_parse_sdk; // ignore_for_file: invalid_use_of_protected_member class ParseLiveList { - ParseLiveList._(this._query, this._listeningIncludes, this._lazyLoading) { + ParseLiveList._(this._query, this._listeningIncludes, this._lazyLoading, + {List preloadedColumns = const []}) + : _preloadedColumns = preloadedColumns { _debug = isDebugEnabled(); } @@ -10,7 +12,7 @@ class ParseLiveList { QueryBuilder _query, {bool listenOnAllSubItems, List listeningIncludes, - bool lazyLoading = true}) { + bool lazyLoading = true, List preloadedColumns,}) { final ParseLiveList parseLiveList = ParseLiveList._( _query, listenOnAllSubItems == true @@ -18,18 +20,26 @@ class ParseLiveList { _query.limiters['include']?.toString()?.split(',') ?? []) : _toIncludeMap(listeningIncludes ?? []), - lazyLoading); + lazyLoading,preloadedColumns: preloadedColumns,); - return parseLiveList._init().then((_) { + return parseLiveList._init().then((_) { return parseLiveList; }); } + final QueryBuilder _query; + //The included Items, where LiveList should look for updates. + final Map _listeningIncludes; + final bool _lazyLoading; + final List _preloadedColumns; + List> _list = List>(); StreamController> _eventStreamController; int _nextID = 0; bool _debug; + int get nextID => _nextID++; + /// is object1 listed after object2? /// can return null bool after(T object1, T object2) { @@ -84,14 +94,6 @@ class ParseLiveList { return null; } - int get nextID => _nextID++; - - final QueryBuilder _query; - //The included Items, where LiveList should look for updates. - final Map _listeningIncludes; - - final bool _lazyLoading; - int get size { return _list.length; } @@ -127,19 +129,17 @@ class ParseLiveList { final QueryBuilder query = QueryBuilder.copy(_query); if (_debug) print('ParseLiveList: lazyLoading is ${_lazyLoading ? 'on' : 'off'}'); - if (_lazyLoading) { - if (query.limiters.containsKey('order')) { - query.keysToReturn( - query.limiters['order'].toString().split(',').map((String string) { + final List keys = _preloadedColumns?.toList() ?? []; + if (_lazyLoading && query.limiters.containsKey('order')) + keys.addAll( + query.limiters['order'].toString().split(',').map((String string) { if (string.startsWith('-')) { return string.substring(1); } return string; - }).toList()); - } else { - query.keysToReturn(List()); - } - } + }), + ); + query.keysToReturn(keys); return await query.query(); } @@ -449,6 +449,13 @@ class ParseLiveList { return null; } + T getPreLoadedAt(int index) { + if (index < _list.length) { + return _list[index].object; + } + return null; + } + void dispose() { if (_liveQuerySubscription != null) { LiveQuery().client.unSubscribe(_liveQuerySubscription); @@ -739,12 +746,17 @@ typedef StreamGetter = Stream Function(); typedef DataGetter = T Function(); class ParseLiveListElementSnapshot { - ParseLiveListElementSnapshot({this.loadedData, this.error}); + ParseLiveListElementSnapshot( + {this.loadedData, this.error, this.preLoadedData}); final T loadedData; + final T preLoadedData; + final ParseError error; bool get hasData => loadedData != null; + bool get hasPreLoadedData => preLoadedData != null; + bool get failed => error != null; } diff --git a/packages/flutter/lib/src/utils/parse_live_list.dart b/packages/flutter/lib/src/utils/parse_live_list.dart index a4674dac5..d80efed77 100644 --- a/packages/flutter/lib/src/utils/parse_live_list.dart +++ b/packages/flutter/lib/src/utils/parse_live_list.dart @@ -21,6 +21,7 @@ class ParseLiveListWidget extends StatefulWidget { this.listenOnAllSubItems, this.listeningIncludes, this.lazyLoading = true, + this.preloadedColumns, }) : super(key: key); final sdk.QueryBuilder query; @@ -42,6 +43,7 @@ class ParseLiveListWidget extends StatefulWidget { final List listeningIncludes; final bool lazyLoading; + final List preloadedColumns; @override _ParseLiveListWidgetState createState() => _ParseLiveListWidgetState( @@ -50,6 +52,7 @@ class ParseLiveListWidget extends StatefulWidget { listenOnAllSubItems: listenOnAllSubItems, listeningIncludes: listeningIncludes, lazyLoading: lazyLoading, + preloadedColumns: preloadedColumns, ); static Widget defaultChildBuilder( @@ -79,12 +82,14 @@ class _ParseLiveListWidgetState @required this.removedItemBuilder, bool listenOnAllSubItems, List listeningIncludes, - bool lazyLoading = true}) { + bool lazyLoading = true, + List preloadedColumns}) { sdk.ParseLiveList.create( query, listenOnAllSubItems: listenOnAllSubItems, listeningIncludes: listeningIncludes, lazyLoading: lazyLoading, + preloadedColumns: preloadedColumns, ).then((sdk.ParseLiveList value) { setState(() { _liveList = value; @@ -107,6 +112,7 @@ class _ParseLiveListWidgetState sizeFactor: animation, duration: widget.duration, loadedData: () => event.object, + preLoadedData: () => event.object, ), duration: widget.duration); } @@ -146,6 +152,7 @@ class _ParseLiveListWidgetState _liveList?.getIdentifier(index) ?? '_NotFound'), stream: () => _liveList?.getAt(index), loadedData: () => _liveList?.getLoadedAt(index), + preLoadedData: () => _liveList?.getPreLoadedAt(index), sizeFactor: animation, duration: widget.duration, childBuilder: @@ -168,6 +175,7 @@ class ParseLiveListElementWidget {Key key, this.stream, this.loadedData, + this.preLoadedData, @required this.sizeFactor, @required this.duration, @required this.childBuilder}) @@ -175,32 +183,36 @@ class ParseLiveListElementWidget final sdk.StreamGetter stream; final sdk.DataGetter loadedData; + final sdk.DataGetter preLoadedData; final Animation sizeFactor; final Duration duration; final ChildBuilder childBuilder; @override _ParseLiveListElementWidgetState createState() { - return _ParseLiveListElementWidgetState(loadedData, stream); + return _ParseLiveListElementWidgetState( + loadedData, preLoadedData, stream); } } class _ParseLiveListElementWidgetState extends State> with SingleTickerProviderStateMixin { - _ParseLiveListElementWidgetState( - sdk.DataGetter loadedDataGetter, sdk.StreamGetter stream) { - _snapshot = - sdk.ParseLiveListElementSnapshot(loadedData: loadedDataGetter()); + _ParseLiveListElementWidgetState(sdk.DataGetter loadedDataGetter, + sdk.DataGetter preLoadedDataGetter, sdk.StreamGetter stream) { + _snapshot = sdk.ParseLiveListElementSnapshot( + loadedData: loadedDataGetter(), preLoadedData: preLoadedDataGetter()); if (stream != null) { _streamSubscription = stream().listen( (T data) { if (widget != null) { setState(() { - _snapshot = sdk.ParseLiveListElementSnapshot(loadedData: data); + _snapshot = sdk.ParseLiveListElementSnapshot( + loadedData: data, preLoadedData: data); }); } else { - _snapshot = sdk.ParseLiveListElementSnapshot(loadedData: data); + _snapshot = sdk.ParseLiveListElementSnapshot( + loadedData: data, preLoadedData: data); } }, onError: (Object error) { From 9e0c64f82ba03e453075671d92f2c7c2bd6ce400 Mon Sep 17 00:00:00 2001 From: Maximilian Fischer Date: Sun, 27 Sep 2020 21:20:27 +0200 Subject: [PATCH 2/4] LiveList: fixed bug with lazyloading=false --- .../dart/lib/src/utils/parse_live_list.dart | 24 ++++++++++--------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/packages/dart/lib/src/utils/parse_live_list.dart b/packages/dart/lib/src/utils/parse_live_list.dart index 63822205b..ddc0aae30 100644 --- a/packages/dart/lib/src/utils/parse_live_list.dart +++ b/packages/dart/lib/src/utils/parse_live_list.dart @@ -129,17 +129,19 @@ class ParseLiveList { final QueryBuilder query = QueryBuilder.copy(_query); if (_debug) print('ParseLiveList: lazyLoading is ${_lazyLoading ? 'on' : 'off'}'); - final List keys = _preloadedColumns?.toList() ?? []; - if (_lazyLoading && query.limiters.containsKey('order')) - keys.addAll( - query.limiters['order'].toString().split(',').map((String string) { - if (string.startsWith('-')) { - return string.substring(1); - } - return string; - }), - ); - query.keysToReturn(keys); + if(_lazyLoading) { + final List keys = _preloadedColumns?.toList() ?? []; + if (_lazyLoading && query.limiters.containsKey('order')) + keys.addAll( + query.limiters['order'].toString().split(',').map((String string) { + if (string.startsWith('-')) { + return string.substring(1); + } + return string; + }), + ); + query.keysToReturn(keys); + } return await query.query(); } From 0b6b1f9fad3e0e3a989e07343890a851ececef03 Mon Sep 17 00:00:00 2001 From: Maximilian Fischer Date: Sun, 27 Sep 2020 21:26:28 +0200 Subject: [PATCH 3/4] formatting --- .../dart/lib/src/utils/parse_live_list.dart | 31 ++++++++++--------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/packages/dart/lib/src/utils/parse_live_list.dart b/packages/dart/lib/src/utils/parse_live_list.dart index ddc0aae30..fd29f9235 100644 --- a/packages/dart/lib/src/utils/parse_live_list.dart +++ b/packages/dart/lib/src/utils/parse_live_list.dart @@ -9,20 +9,23 @@ class ParseLiveList { } static Future> create( - QueryBuilder _query, - {bool listenOnAllSubItems, - List listeningIncludes, - bool lazyLoading = true, List preloadedColumns,}) { + QueryBuilder _query, { + bool listenOnAllSubItems, + List listeningIncludes, + bool lazyLoading = true, + List preloadedColumns, + }) { final ParseLiveList parseLiveList = ParseLiveList._( - _query, - listenOnAllSubItems == true - ? _toIncludeMap( - _query.limiters['include']?.toString()?.split(',') ?? - []) - : _toIncludeMap(listeningIncludes ?? []), - lazyLoading,preloadedColumns: preloadedColumns,); - - return parseLiveList._init().then((_) { + _query, + listenOnAllSubItems == true + ? _toIncludeMap( + _query.limiters['include']?.toString()?.split(',') ?? []) + : _toIncludeMap(listeningIncludes ?? []), + lazyLoading, + preloadedColumns: preloadedColumns, + ); + + return parseLiveList._init().then((_) { return parseLiveList; }); } @@ -129,7 +132,7 @@ class ParseLiveList { final QueryBuilder query = QueryBuilder.copy(_query); if (_debug) print('ParseLiveList: lazyLoading is ${_lazyLoading ? 'on' : 'off'}'); - if(_lazyLoading) { + if (_lazyLoading) { final List keys = _preloadedColumns?.toList() ?? []; if (_lazyLoading && query.limiters.containsKey('order')) keys.addAll( From 5063456f69a1d469ff48d6c0af4baa8d76b1c25c Mon Sep 17 00:00:00 2001 From: Maximilian Fischer Date: Fri, 2 Oct 2020 13:30:41 +0200 Subject: [PATCH 4/4] Add README section for flutter --- packages/flutter/README.md | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/packages/flutter/README.md b/packages/flutter/README.md index 03e2094c5..7fd06cba4 100644 --- a/packages/flutter/README.md +++ b/packages/flutter/README.md @@ -597,6 +597,38 @@ To activate listening for updates on all included objects, add `listenOnAllSubIt If you want ParseLiveList to listen for updates on only some sub-objects, use `listeningIncludes: const [/*all the included sub-objects*/]` instead. Just as QueryBuilder, ParseLiveList supports nested sub-objects too. +### Lazy loading +By default, ParseLiveList lazy loads the content. +You can avoid that by setting `lazyLoading: false`. +In case you want to use lazyLoading but you need some columns to be preloaded, you can provide a list of `preloadedColumns`. +Preloading fields of a pointer is supported by using the dot-notation. +You can access the preloaded data is stored in the `preLoadedData` field of the `ParseLiveListElementSnapshot`. +```dart +ParseLiveListWidget( + query: query, + lazyLoading: true, + preloadedColumns: ["test1", "sender.username"], + childBuilder: + (BuildContext context, ParseLiveListElementSnapshot snapshot) { + if (snapshot.failed) { + return const Text('something went wrong!'); + } else if (snapshot.hasData) { + return ListTile( + title: Text( + snapshot.loadedData.get("text"), + ), + ); + } else { + return ListTile( + title: Text( + "loading comment from: ${snapshot.preLoadedData?.get("sender")?.get("username")}", + ), + ); + } + }, +); +``` + **NOTE:** To use this features you have to enable [Live Queries](#live-queries) first. ## Users