How to consume GraphQL Subscription with Flutter?

3,967

Solution 1

You can check the next library https://github.com/zino-app/graphql-flutter

Solution 2

My GraphqlServer runs a subscription named getLogs which returns the log information in the following format.

{
  "data": {
    "getLogs": {
      "timeStamp": "18:09:24",
      "logLevel": "DEBUG",
      "file": "logger.py",
      "function": "init",
      "line": "1",
      "message": "Hello from logger.py"
    }
  }
}

If you are like me who wants to use only the GraphQL Client directly, then following sample could help.

import 'package:graphql/client.dart';
import 'package:graphql/internal.dart';
import 'package:flutter/material.dart';
import 'dart:async';

class LogPuller extends StatefulWidget {
  static final WebSocketLink _webSocketLink = WebSocketLink(
    url: 'ws://localhost:8000/graphql/',
    config: SocketClientConfig(
      autoReconnect: true,
    ),
  );

  static final Link _link = _webSocketLink;

  @override
  _LogPullerState createState() => _LogPullerState();
}

class _LogPullerState extends State<LogPuller> {
  final GraphQLClient _client = GraphQLClient(
    link: LogPuller._link,
    cache: InMemoryCache(),
  );

  // the subscription query should be of the following format. Note how the 'GetMyLogs' is used as the operation name below.
  final String subscribeQuery = '''
    subscription GetMyLogs{
      getLogs{
        timeStamp
        logLevel
        file
        function
        line
        message
      }
    }
    ''';
  Operation operation;

  Stream<FetchResult> _logStream;

  @override
  void initState() {
    super.initState();
    // note operation name is important. If not provided the stream subscription fails after first pull.
    operation = Operation(document: subscribeQuery, operationName: 'GetMyLogs');
    _logStream = _client.subscribe(operation);
  }

  @override
  Widget build(BuildContext context) {
    return StreamBuilder(
      stream: _logStream,
      builder: (context, snapshot) {
        if (snapshot.connectionState == ConnectionState.waiting) {
          return Center(
            child: Container(
              child: CircularProgressIndicator(
                strokeWidth: 1.0,
              ),
            ),
          );
        }
        if (snapshot.hasData) {
          return Center(
            child: Text(
              snapshot.data.data['getLogs']
                  ['message'], // This will change according to you needs.
            ),
          );
        }
        return Container();
      },
    );
  }
}

As I am using a StreamBuilder to build the widget it will take care of closing the stream. If this is not the case for you, stream.listen() method will return a StreamSubscription<FetchResult> object which you can call the cancel() method which can be done inside dispose() method of a stateful widget or any such method for a standalone Dart client.

Solution 3

Just find out the bug in this library, Just open the subscription.dart file by ctrl+click on Subscription. In that file, it is easy to see that socketClient variable is null. So just define it in initState() function as shown in the docs. Restart your app. And it works like a charm. So, basically, you just need to initialize that variable in the subscription.dart file.

Share:
3,967
Joseph Arriaza
Author by

Joseph Arriaza

I am a full stack developer that have knowledge in a lot of technologies, like front end frameworks, like Angular, AngularJS, ReactJS, etc, also I have a knowledge using back end technologies, building APIs using Java, PHP &amp; C#. In my current work, we give services to companies in the US, so far, I have worked for Telecom Service Bureau building APIs and Front End interfaces, and also I work for Front Stream giving support to its system.

Updated on December 07, 2022

Comments

  • Joseph Arriaza
    Joseph Arriaza over 1 year

    I am creating a subscription with GraphQL, and I need to consume that subscription with Flutter, but I don't know how to do that, the thing that I need is something like a UI component that would be tied to a subscription and it will be automatically refreshed.

    I will appreciate any feedback.

  • Joseph Arriaza
    Joseph Arriaza over 5 years
    I was trying to use that library, but I don't know where I should initialize socketClient, could you give me any help?