my pubspec.yaml
dev_dependencies:
flutter_test:
sdk: flutter
graphql_flutter: ^4.0.0
roomctrl.dart
import 'package:flutter/material.dart';
import 'package:graphql_flutter/graphql_flutter.dart';
import 'package:innospace/config/appsync-service.dart';
import 'package:innospace/config/client_provider.dart';
class RoomCtrl extends StatefulWidget {
RoomCtrl({Key key}) : super(key: key);
_RoomCtrlState createState() => _RoomCtrlState();
}
class _RoomCtrlState extends State<RoomCtrl> {
@override
void initState() {
super.initState();
}
@override
Widget build(BuildContext context) {
return ClientProvider(
child: Scaffold(
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
Subscription(
options:SubscriptionOptions(
document: gql(AppSyncService.onUpdateStateTestSubscription)),
builder: (result) {
if (result.hasException) {
return Text(result.exception.toString());
}
if (result.isLoading) {
return Center(
child: const CircularProgressIndicator(),
);
}
return Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
Container(
child: Text(result.data.length.toString()),
)
],
),
);
},
)
],
),
),
));
}
}
client_provider.dart
import 'package:graphql_flutter/graphql_flutter.dart';
import 'package:flutter/material.dart';
import 'constants.dart';
String uuidFromObject(Object object) {
if (object is Map<String, Object>) {
final String typeName = object['__typename'] as String;
final String id = object['id'].toString();
if (typeName != null && id != null) {
return <String>[typeName, id].join('/');
}
}
return null;
}
ValueNotifier<GraphQLClient> clientFor() {
const dynamic headers = {
"headers": {
"host": AWS_APP_SYNC_ENDPOINT_AUTHORITY,
"x-api-key": AWS_APP_SYNC_KEY
}};
const sClient= SocketClientConfig(
autoReconnect : true,
initialPayload: headers
);
final WebSocketLink _webSocketLink =new WebSocketLink(AWS_APP_SYNC_ENDPOINT_WSS, config:sClient );
final Link link = _webSocketLink;
return ValueNotifier<GraphQLClient>(
GraphQLClient(
cache: GraphQLCache(),
link: link,
),
);
}
/// Wraps the root application with the `graphql_flutter` client.
/// We use the cache for all state management.
class ClientProvider extends StatelessWidget {
ClientProvider({
@required this.child,
}) : client = clientFor();
final Widget child;
final ValueNotifier<GraphQLClient> client;
@override
Widget build(BuildContext context) {
return GraphQLProvider(
client: client,
child: child,
);
}
}
constants.dart
[https://docs.aws.amazon.com/appsync/latest/devguide/real-time-websocket-client.html][1]
const AWS_APP_SYNC_ENDPOINT_AUTHORITY = "xxxxxxxxxxxxxxxxxxxxx.appsync-api.ap-southeast-2.amazonaws.com";
const AWS_APP_SYNC_ENDPOINT_WSS = "wss://xxxxxxxxxxxxxxxxxxxxx.appsync-realtime-api.ap-southeast-2.amazonaws.com/graphql?header=base64encryption(xxx-xxxxxxxxxxxxxxxxxx as per aws)&payload=e30=";
const AWS_APP_SYNC_KEY = "xxx-xxxxxxxxxxxxxxxxxx";
subscription query
static String onUpdateStateTestSubscription = '''
subscription OnUpdateStateTest {
onUpdateStateTest {
__typename
RoomId
RoomName
}
}''';
console
Connecting to websocket: wss://xxxxxxxxxxxxxxxxxxxxx.appsync-realtime-api.ap-southeast-2.amazonaws.com/graphql?header=base64encryption(xxx-xxxxxxxxxxxxxxxxxx as per aws)&payload=e30=...
I/flutter ( 9942): Connected to websocket.
I/flutter ( 9942): Haven't received keep alive message for 30 seconds. Disconnecting..
I/flutter ( 9942): Disconnected from websocket.
I/flutter ( 9942): Scheduling to connect in 5 seconds...
I/flutter ( 9942): Connecting to websocket: wss://xxxxxxxxxxxxxxxxxxxxx.appsync-realtime-api.ap-southeast-2.amazonaws.com/graphql?header=base64encryption(xxx-xxxxxxxxxxxxxxxxxx as per aws)&payload=e30=...
I/flutter ( 9942): Connected to websocket.
I/flutter ( 9942): Haven't received keep alive message for 30 seconds. Disconnecting..
I/flutter ( 9942): Disconnected from websocket.
I/flutter ( 9942): Scheduling to connect in 5 seconds...
Finally output on mobile is showing loading gif i.e CircularProgressIndicator(), means returns always true at "if (result.isLoading)"
[![enter image description here][2]][2]
Could anyone please help!!
note: the same appsync working perfectly in angular application. [1]: https://docs.aws.amazon.com/appsync/latest/devguide/real-time-websocket-client.html [2]: https://i.stack.imgur.com/59KZh.png
See my recent update at the bottom.
I'm actually running into the same problem. I don't have a complete answer but I feel like this is a clue to a partial answer.
From the link:
I've confirmed w/ the GraphiQL tool that I do get a response when I POST my subscription graphql blob. I get a websocket url back along w/ some other items in JSON. I haven't figured out how to capture that response in Flutter yet but I'll update this if I find that piece as well.
From there, I believe we'd need to dynamically create the websocket from that new url and send our subscription graphql blob to that.
Absolutely, this is convoluted but it's the path I'm proceeding with for now.
UPDATE: AWS Amplify for Flutter now supports subscriptions! I am using a hybrid solution. I have
flutter_graphql
andartemis
for mutations/queries. For subscriptions I am usingamplify_api: '<1.0.0'
. It was just released in the past weeks. It actually only took me a few minutes to get it working. Amplify automatically does the URL resolution and authentication for you.Link to official docs
You'll need to generate an
amplifyconfiguration.dart
that is specific for your AWS endpoint and add it to your project. The AWS docs cover this and the person that setup your AWS endpoint should know exactly what you need.Example from link:
Don't forget to unsubscribe: