Skip to content

Commit f8af2b6

Browse files
authored
Added generics to Query/LiveQuery (#336)
1 parent f814dc9 commit f8af2b6

File tree

4 files changed

+52
-39
lines changed

4 files changed

+52
-39
lines changed

lib/src/network/parse_live_query.dart

Lines changed: 28 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,12 @@ enum LiveQueryEvent { create, enter, update, leave, delete, error }
1313

1414
const String _printConstLiveQuery = 'LiveQuery: ';
1515

16-
class Subscription {
17-
Subscription(this.query, this.requestId);
18-
QueryBuilder query;
16+
class Subscription<T extends ParseObject> {
17+
Subscription(this.query, this.requestId, {T copyObject}) {
18+
_copyObject = copyObject;
19+
}
20+
QueryBuilder<T> query;
21+
T _copyObject;
1922
int requestId;
2023
bool _enabled = false;
2124
final List<String> _liveQueryEvent = <String>[
@@ -30,6 +33,10 @@ class Subscription {
3033
void on(LiveQueryEvent op, Function callback) {
3134
eventCallbacks[_liveQueryEvent[op.index]] = callback;
3235
}
36+
37+
T get copyObject {
38+
return _copyObject;
39+
}
3340
}
3441

3542
enum LiveQueryClientEvent { CONNECTED, DISCONNECTED, USER_DISCONNECTED }
@@ -52,7 +59,6 @@ class LiveQueryReconnectingController with WidgetsBindingObserver {
5259

5360
LiveQueryReconnectingController(
5461
this._reconnect, this._eventStream, this.debug) {
55-
5662
Connectivity().checkConnectivity().then(_connectivityChanged);
5763
Connectivity().onConnectivityChanged.listen(_connectivityChanged);
5864

@@ -81,7 +87,7 @@ class LiveQueryReconnectingController with WidgetsBindingObserver {
8187
WidgetsBinding.instance.addObserver(this);
8288
}
8389

84-
void _connectivityChanged(ConnectivityResult state){
90+
void _connectivityChanged(ConnectivityResult state) {
8591
if (!_isOnline && state != ConnectivityResult.none) _retryState = 0;
8692
_isOnline = state != ConnectivityResult.none;
8793
if (debug) print('$DEBUG_TAG: $state');
@@ -107,9 +113,9 @@ class LiveQueryReconnectingController with WidgetsBindingObserver {
107113
retryInterval[_retryState] >= 0) {
108114
_currentTimer =
109115
Timer(Duration(milliseconds: retryInterval[_retryState]), () {
110-
_currentTimer = null;
111-
_reconnect();
112-
});
116+
_currentTimer = null;
117+
_reconnect();
118+
});
113119
if (debug)
114120
print('$DEBUG_TAG: Retrytimer set to ${retryInterval[_retryState]}ms');
115121
if (_retryState < retryInterval.length - 1) _retryState++;
@@ -128,7 +134,7 @@ class Client {
128134
_client = client ??
129135
ParseHTTPClient(
130136
sendSessionId:
131-
autoSendSessionId ?? ParseCoreData().autoSendSessionId,
137+
autoSendSessionId ?? ParseCoreData().autoSendSessionId,
132138
securityContext: ParseCoreData().securityContext);
133139

134140
_debug = isDebugEnabled(objectLevelDebug: debug);
@@ -142,7 +148,7 @@ class Client {
142148
}
143149

144150
reconnectingController = LiveQueryReconnectingController(
145-
() => reconnect(userInitialized: false), getClientEventStream, _debug);
151+
() => reconnect(userInitialized: false), getClientEventStream, _debug);
146152
}
147153
static Client get instance => _getInstance();
148154
static Client _instance;
@@ -206,21 +212,24 @@ class Client {
206212
.add(LiveQueryClientEvent.USER_DISCONNECTED);
207213
}
208214

209-
Future<Subscription> subscribe(QueryBuilder query) async {
215+
Future<Subscription<T>> subscribe<T extends ParseObject>(
216+
QueryBuilder<T> query,
217+
{T copyObject}) async {
210218
if (_webSocket == null) {
211219
await _clientEventStream.any((LiveQueryClientEvent event) =>
212-
event == LiveQueryClientEvent.CONNECTED);
220+
event == LiveQueryClientEvent.CONNECTED);
213221
}
214222
final int requestId = _requestIdGenerator();
215-
final Subscription subscription = Subscription(query, requestId);
223+
final Subscription<T> subscription =
224+
Subscription<T>(query, requestId, copyObject: copyObject);
216225
_requestSubScription[requestId] = subscription;
217226
//After a client connects to the LiveQuery server,
218227
//it can send a subscribe message to subscribe a ParseQuery.
219228
_subscribeLiveQuery(subscription);
220229
return subscription;
221230
}
222231

223-
void unSubscribe(Subscription subscription) {
232+
void unSubscribe<T extends ParseObject>(Subscription<T> subscription) {
224233
//Mount message for Unsubscribe
225234
final Map<String, dynamic> unsubscribeMessage = <String, dynamic>{
226235
'op': 'unsubscribe',
@@ -382,10 +391,12 @@ class Client {
382391
final String className = map['className'];
383392
if (className == '_User') {
384393
subscription.eventCallbacks[actionData['op']](
385-
ParseUser(null, null, null).fromJson(map));
394+
(subscription.copyObject ?? ParseUser(null, null, null))
395+
.fromJson(map));
386396
} else {
387397
subscription.eventCallbacks[actionData['op']](
388-
ParseObject(className).fromJson(map));
398+
(subscription.copyObject ?? ParseObject(className))
399+
.fromJson(map));
389400
}
390401
} else {
391402
subscription.eventCallbacks[actionData['op']](actionData);
@@ -399,7 +410,7 @@ class LiveQuery {
399410
_client = client ??
400411
ParseHTTPClient(
401412
sendSessionId:
402-
autoSendSessionId ?? ParseCoreData().autoSendSessionId,
413+
autoSendSessionId ?? ParseCoreData().autoSendSessionId,
403414
securityContext: ParseCoreData().securityContext);
404415

405416
_debug = isDebugEnabled(objectLevelDebug: debug);

lib/src/network/parse_query.dart

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -296,13 +296,14 @@ class QueryBuilder<T extends ParseObject> {
296296
/// Finishes the query and calls the server
297297
///
298298
/// Make sure to call this after defining your queries
299-
Future<ParseResponse> query() async {
300-
return object.query(buildQuery());
299+
Future<ParseResponse> query<T extends ParseObject>() async {
300+
return object.query<T>(buildQuery());
301301
}
302302

303-
Future<ParseResponse> distinct(String className) async {
303+
Future<ParseResponse> distinct<T extends ParseObject>(
304+
String className) async {
304305
final String queryString = 'distinct=$className';
305-
return object.distinct(queryString);
306+
return object.distinct<T>(queryString);
306307
}
307308

308309
///Counts the number of objects that match this query

lib/src/objects/parse_object.dart

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,9 @@ class ParseObject extends ParseBase implements ParseCloneable {
8484
final Uri url = getSanitisedUri(_client, '$_path/$objectId');
8585
final String body = json.encode(toJson(forApiRQ: true));
8686
_saveChanges();
87-
final Map<String, String> headers = {keyHeaderContentType:keyHeaderContentTypeJson};
87+
final Map<String, String> headers = {
88+
keyHeaderContentType: keyHeaderContentTypeJson
89+
};
8890
final Response result =
8991
await _client.put(url, body: body, headers: headers);
9092
return handleResponse<ParseObject>(
@@ -483,8 +485,7 @@ class ParseObject extends ParseBase implements ParseCloneable {
483485
_savingChanges.remove(key);
484486

485487
if (offlineOnly) {
486-
return ParseResponse()
487-
..success = true;
488+
return ParseResponse()..success = true;
488489
}
489490

490491
try {
@@ -499,8 +500,7 @@ class ParseObject extends ParseBase implements ParseCloneable {
499500
_unsavedChanges[key] = object;
500501
_savingChanges[key] = object;
501502
} else {
502-
return ParseResponse()
503-
..success = true;
503+
return ParseResponse()..success = true;
504504
}
505505
}
506506
} on Exception {
@@ -509,41 +509,41 @@ class ParseObject extends ParseBase implements ParseCloneable {
509509
_savingChanges[key] = object;
510510
}
511511

512-
return ParseResponse()
513-
..success = false;
512+
return ParseResponse()..success = false;
514513
}
515514

516515
/// Can be used to create custom queries
517-
Future<ParseResponse> query(String query) async {
516+
Future<ParseResponse> query<T extends ParseObject>(String query) async {
518517
try {
519518
final Uri url = getSanitisedUri(_client, '$_path', query: query);
520519
final Response result = await _client.get(url);
521-
return handleResponse<ParseObject>(
520+
return handleResponse<T>(
522521
this, result, ParseApiRQ.query, _debug, parseClassName);
523522
} on Exception catch (e) {
524523
return handleException(e, ParseApiRQ.query, _debug, parseClassName);
525524
}
526525
}
527526

528-
Future<ParseResponse> distinct(String query) async {
527+
Future<ParseResponse> distinct<T extends ParseObject>(String query) async {
529528
try {
530529
final Uri url = getSanitisedUri(_client, '$_aggregatepath', query: query);
531530
final Response result = await _client.get(url);
532-
return handleResponse<ParseObject>(
531+
return handleResponse<T>(
533532
this, result, ParseApiRQ.query, _debug, parseClassName);
534533
} on Exception catch (e) {
535534
return handleException(e, ParseApiRQ.query, _debug, parseClassName);
536535
}
537536
}
538537

539538
/// Deletes the current object locally and online
540-
Future<ParseResponse> delete({String id, String path}) async {
539+
Future<ParseResponse> delete<T extends ParseObject>(
540+
{String id, String path}) async {
541541
try {
542542
path ??= _path;
543543
id ??= objectId;
544544
final Uri url = getSanitisedUri(_client, '$_path/$id');
545545
final Response result = await _client.delete(url);
546-
return handleResponse<ParseObject>(
546+
return handleResponse<T>(
547547
this, result, ParseApiRQ.delete, _debug, parseClassName);
548548
} on Exception catch (e) {
549549
return handleException(e, ParseApiRQ.delete, _debug, parseClassName);

lib/src/utils/parse_live_list.dart

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ class ParseLiveList<T extends ParseObject> {
8080
query.keysToReturn(List<String>());
8181
}
8282

83-
return await query.query();
83+
return await query.query<T>();
8484
}
8585

8686
Future<void> _init() async {
@@ -96,8 +96,9 @@ class ParseLiveList<T extends ParseObject> {
9696

9797
LiveQuery()
9898
.client
99-
.subscribe(QueryBuilder<T>.copy(_query))
100-
.then((Subscription subscription) {
99+
.subscribe<T>(QueryBuilder<T>.copy(_query),
100+
copyObject: _query.object.clone(_query.object.toJson()))
101+
.then((Subscription<T> subscription) {
101102
_liveQuerySubscription = subscription;
102103
subscription.on(LiveQueryEvent.create, _objectAdded);
103104
subscription.on(LiveQueryEvent.update, _objectUpdated);
@@ -131,7 +132,7 @@ class ParseLiveList<T extends ParseObject> {
131132
.isAfter(currentObject.get<DateTime>(keyVarUpdatedAt))) {
132133
QueryBuilder<T> queryBuilder = QueryBuilder<T>.copy(_query)
133134
..whereEqualTo(keyVarObjectId, currentObjectId);
134-
queryBuilder.query().then((ParseResponse result) {
135+
queryBuilder.query<T>().then((ParseResponse result) {
135136
if (result.success) {
136137
_objectUpdated(result.results.first);
137138
}
@@ -206,7 +207,7 @@ class ParseLiveList<T extends ParseObject> {
206207
..whereEqualTo(
207208
keyVarObjectId, _list[index].object.get<String>(keyVarObjectId))
208209
..setLimit(1);
209-
final ParseResponse response = await queryBuilder.query();
210+
final ParseResponse response = await queryBuilder.query<T>();
210211
if (response.success && response.results != null) {
211212
_list[index].object = response.results.first;
212213
} else {

0 commit comments

Comments
 (0)