graphql-flutter

repository·main·Indexed 25 days ago

https://github.com/zino-hofmann/graphql-flutter

A high-performance suite of Dart and Flutter packages for interacting with GraphQL servers, inspired by the Apollo GraphQL client and leveraging Dart Streams. It provides a GraphQL client, a set of Flutter widgets (Query, Mutation, Subscription), and hooks for flutter-hooks users. The library supports type-safe operations via compatibility with graphql_codegen and offers persistent storage using HiveStore.

Tokens
18.6K
Snippets
46
Records
104
Agent score
85%

What's inside graphql-flutter

  1. Overview of GraphQL Flutter packages

    main

    GraphQL Flutter is a collection of packages designed to work with GraphQL servers in Dart and Flutter. It combines GraphQL benefits with Dart Streams for high performance. The project is split into two primary packages:

    • graphql: The core client implementation used to interact with any GraphQL server.
    • graphql_flutter: A Flutter-specific wrapper that provides Widgets around the core graphql API.

    Additional utility tools available in the ecosystem include graphql_flutter_bloc, graphql_codegen, and graphql-cache-inspector.

  2. Understand the graphql-flutter architecture

    main
    The graphql/client.dart is heavily modeled after the Apollo Client. It uses a layered design for its cache and an execution 'link' layer. The core execution logic is handled by the QueryManager, which manages individual requests, optimistic data reading, and cache writes. The streaming capabilities of the library are powered by ObservableQuery.
  3. Core features of GraphQL Flutter

    main

    The GraphQL Flutter ecosystem provides the following capabilities:

    • Operations: Support for Queries, Mutations, and Subscriptions.
    • Caching: Both in-memory and persistent caching options.
    • Data Handling: Support for GraphQL Upload and Optimistic results (via graphql_flutter).
    • Advanced Client Features: Query polling and rebroadcasting, operation cancellation, and client-state management via direct cache access API.
    • Extensibility: Modular architecture using Links.

    Note: Automatic Persisted Queries is currently marked as out of service.

  4. Follow the graphql-flutter code style

    main

    To maintain consistency in the codebase, adhere to these rules:

    • Testing: All features or bug fixes must be accompanied by one or more unit tests (specs).
    • Documentation: All public API methods must be documented.
    • Guidelines: Follow the Effective Dart: Style Guidelines.
    • Simplicity: If the correct implementation is unclear, implement the simplest possible solution to avoid over-engineering. Use /* FIXME: */ to mark areas for future optimization or to note ugly corner cases.
    • Reviewability: Keep patches minimal. Make a single change at a time to ensure reviews are manageable.
  5. Customize iOS Launch Screen Assets

    main

    To change the launch screen image for the iOS version of the Star Wars example, you can either replace the image files directly in the LaunchImage.imageset directory or use Xcode to manage the assets.

    To use Xcode:

    1. Open the iOS project using open ios/Runner.xcworkspace.
    2. In the Xcode Project Navigator, navigate to Runner/Assets.xcassets.
    3. Drag and drop your desired images into the asset catalog.
    open ios/Runner.xcworkspace
  6. Initialize a GraphQLClient with HttpLink and AuthLink

    main

    To connect to a GraphQL server, create a GraphQLClient using a cache and a link. You can concatenate links, such as using AuthLink to attach a bearer token to an HttpLink.

    final _httpLink = HttpLink(
      'https://api.github.com/graphql',
    );
    
    final _authLink = AuthLink(
      getToken: () async => 'Bearer $YOUR_PERSONAL_ACCESS_TOKEN',
    );
    
    Link _link = _authLink.concat(_httpLink);
    
    final GraphQLClient client = GraphQLClient(
      cache: GraphQLCache(),
      link: _link,
    );
  7. Run the graphql/client.dart example application

    main

    The graphql/client.dart example is a command-line application designed to demonstrate how to use the Dart GraphQL Client independently of Flutter.

    To set up and run the example, follow these steps:

    1. Clone the repository and navigate to the packages/graphql/example directory.
    2. Install all Dart dependencies using your package manager.
    3. Open lib/local.dart and replace <YOUR_PERSONAL_ACCESS_TOKEN> with your actual GitHub personal access token.

    Once configured, you can use the CLI to interact with GitHub repositories.

  8. Use the layered cache and optimistic updates

    main
    The GraphQLCache implements a layered optimism system similar to Apollo. This allows for a clean separation of optimistic data from individual mutations, which are merged at read time. While users can provide a custom Store, the cache normalization logic is primarily handled by the normalize package. For persistent storage, hive_store.dart is the recommended implementation.
  9. Cancel GraphQL Operations

    main

    You can cancel ongoing operations using a CancellationToken or by using convenience methods like queryCancellable and mutateCancellable.

    Using CancellationToken

    final cancellationToken = CancellationToken();
    
    final resultFuture = client.query(
      QueryOptions(
        document: gql(readRepositories),
        variables: {'nRepositories': 50},
        cancellationToken: cancellationToken,
      ),
    );
    
    // Cancel the operation
    cancellationToken.cancel();
    
    final result = await resultFuture;
    if (result.hasException && result.exception!.linkException is CancelledException) {
      print('Operation was cancelled');
    }
    
    cancellationToken.dispose();

    Using queryCancellable and mutateCancellable

    These methods return a CancellableOperation which manages the token automatically.

    // Query
    final operation = client.queryCancellable(
      QueryOptions(
        document: gql(readRepositories),
        variables: {'nRepositories': 50},
      ),
    );
    operation.cancel();
    final result = await operation.result;
    
    // Mutation
    final mutationOp = client.mutateCancellable(
      MutationOptions(
        document: gql(addStar),
        variables: {'starrableId': repositoryID},
      ),
    );
    mutationOp.cancel();
    final result = await mutationOp.result;
    // Using CancellationToken
    final cancellationToken = CancellationToken();
    
    final resultFuture = client.query(
      QueryOptions(
        document: gql(readRepositories),
        variables: {'nRepositories': 50},
        cancellationToken: cancellationToken,
      ),
    );
    
    cancellationToken.cancel();
    
    final result = await resultFuture;
    if (result.hasException && result.exception!.linkException is CancelledException) {
      print('Operation was cancelled');
    }
    
    cancellationToken.dispose();
    
    // Using queryCancellable
    final operation = client.queryCancellable(
      QueryOptions(
        document: gql(readRepositories),
        variables: {'nRepositories': 50},
      ),
    );
    operation.cancel();
    final result = await operation.result;
    
    // Using mutateCancellable
    final mutationOp = client.mutateCancellable(
      MutationOptions(
        document: gql(addStar),
        variables: {'starrableId': repositoryID},
      ),
    );
    mutationOp.cancel();
    final result = await mutationOp.result;