amazon-web-services - aws appsync订阅不适用于flutter graphql_flutter包
问题描述
我的 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,
);
}
}
常量.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";
订阅查询
static String onUpdateStateTestSubscription = '''
subscription OnUpdateStateTest {
onUpdateStateTest {
__typename
RoomId
RoomName
}
}''';
安慰
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...
最后在移动设备上的输出显示正在加载 gif,即 CircularProgressIndicator(),意味着在“if (result.isLoading)”处始终返回 true
[![在此处输入图像描述][2]][2]
谁能帮忙!!
注意:相同的 appsync 在 Angular 应用程序中完美运行。[1]:https ://docs.aws.amazon.com/appsync/latest/devguide/real-time-websocket-client.html [2]:https ://i.stack.imgur.com/59KZh.png
解决方案
在底部查看我最近的更新。
我实际上遇到了同样的问题。我没有完整的答案,但我觉得这是部分答案的线索。
从链接:
据我所知,AppSync 不使用 wss://<your_end_point>。我以前试过这个,我的http连接从来没有“升级到wss”连接。我必须向请求订阅连接的 http 端点发布请求,然后 AWS 返回包含新端点(wss url)、主题和客户端 ID 的连接详细信息。只有这样我才能使用第三方库(使用 AWS 返回的 URL)连接到套接字。我不得不深入研究他们的官方 sdk 来找出这个问题,然后通过反复试验让它工作。
我已使用 GraphiQL 工具确认,当我发布订阅 graphql blob 时确实会收到响应。我得到一个 websocket url 以及 JSON 中的其他一些项目。我还没有想出如何在 Flutter 中捕获该响应,但如果我也找到了那篇文章,我会更新它。
从那里开始,我相信我们需要从该新 url 动态创建 websocket 并将我们的订阅 graphql blob 发送到那里。
绝对,这是令人费解的,但这是我现在要走的路。
更新: AWS Amplify for Flutter 现在支持订阅!我正在使用混合解决方案。我有flutter_graphql
和artemis
用于突变/查询。对于我正在使用的订阅amplify_api: '<1.0.0'
。它在过去几周刚刚发布。实际上,我只花了几分钟就让它工作了。Amplify 会自动为您进行 URL 解析和身份验证。
您需要生成一个amplifyconfiguration.dart
特定于您的 AWS 终端节点并将其添加到您的项目中。AWS 文档涵盖了这一点,设置您的 AWS 终端节点的人应该确切地知道您需要什么。
来自链接的示例:
try {
String graphQLDocument = '''subscription OnCreateTodo {
onCreateTodo {
id
name
description
}
}''';
var operation = Amplify.API.subscribe(
request: GraphQLRequest<String>(document: graphQLDocument),
onData: (event) {
print('Subscription event data received: ${event.data}');
},
onEstablished: () {
print('Subscription established');
},
onError: (e) {
print('Subscription failed with error: $e');
},
onDone: () {
print('Subscription has been closed successfully');
});
} on ApiException catch (e) {
print('Failed to establish subscription: $e');
}
不要忘记取消订阅:
// Cancel the subscription when you're finished with it
operation.cancel();
推荐阅读
- ios - I can't set the uipickerview datasource and delegate from an outside file
- python - Invalid response when I use my socket code
- windows - Calling an Ansible script inside of a ansible script and/or within a Loop module
- reactjs - React 与对象和嵌套数组的状态比较
- python - pipenv 是每次都下载包还是使用像 pip 这样的缓存包?
- java - 如果没有 Java 的 trim() 方法,你将如何递归地修剪字符串?
- selenium - IRetryAnalyzer 为定义为 SoftAssert 的测试用例生成不正确的结果
- docker - 我可以通过使用 docker compose 缩放 kafka 从分配的端口设置广告端口吗?
- flutter - 如何实现一个自适应可用空间的小部件,在空间不可用时缩小自身的一部分
- c# - 关于Unity序列化公共数组类的问题