Upgrade to Pro — share decks privately, control downloads, hide ads and more …

GraphQLを使ってアプリを作っている話 / The story of building a...

GraphQLを使ってアプリを作っている話 / The story of building an app using GraphQL

# 【Online】Flutter Meetupで発表した資料です。
https://flutter-jp.connpass.com/event/159013/

# GraphQLの公式ページ
https://graphql.org/

# Flutter chat application on GitHub
https://github.com/kwmt/flutter-inconne

# json_serializable
https://pub.dev/packages/json_serializable

# json_annotation
https://pub.dev/packages/json_annotation

# graphql_fragment_generator
https://pub.dev/packages/graphql_fragment_generator

Yasutaka Kawamoto

July 14, 2020
Tweet

More Decks by Yasutaka Kawamoto

Other Decks in Programming

Transcript

  1. • Տຊ ହ޹ • AndroidɺiOSΤϯδχΞ
 @גࣜձࣾtech vein ࣗݾ঺հ • Flutter৮Γ࢝Ίɿ2018೥6݄ࠒ͔Β

    • ݸਓͰνϟοτΞϓϦΛ2018೥຤ʹϦϦʔε
 https://github.com/kwmt/flutter-inconne • ιϑτ΢ΣΞσβΠϯ2019೥4݄߸ʹ
 Flutterೖ໳ͷهࣄΛدߘ • 2019೥3݄ɿFlutter Meetup TokyoͰొஃ FlutterͱͷؔΘΓ
  2. ϑϥάϝϯτ { hero { name friend { ...characterFragment } }

    } fragment characterFragment on Character { name }
  3. ϑϥάϝϯτ { hero { name friend { ...characterFragment } }

    } fragment characterFragment on Character { name }
  4. Opectaion Type ͱ Operation Name query HeroName { hero {

    name } } Operation Type Operation Name
  5. λΠϜϥΠϯͷΫΤϦ { timeline { user { name } image_url comment

    } } checkIn user.name image_url comment timeline
  6. GraphQLClientੜ੒ GraphQLClient client() { final HttpLink _httpLink = HttpLink( uri:

    'https://api.github.com/graphql', ); final AuthLink _authLink = AuthLink( getToken: () async => 'Bearer $PERSONAL_ACCESS_TOKEN', ); final Link _link = _authLink.concat(_httpLink); return GraphQLClient( cache: InMemoryCache(), link: _link, ); }
  7. GraphQLClientͰAPIϦΫΤετ class Session { Session(this._client); final GraphQLClient _client; Future<T> request<T>(Request<T>

    request) async { QueryResult result = await _client.query( QueryOptions( documentNode: gql(request.document), variables: request.variables ?? {}, ) ); return request.parseResponse(result.data); } }
  8. GraphQLClientͰAPIϦΫΤετ class Session { Session(this._client); final GraphQLClient _client; Future<T> request<T>(Request<T>

    request) async { QueryResult result = await _client.query( QueryOptions( documentNode: gql(request.document), variables: request.variables ?? {}, ) ); return request.parseResponse(result.data); } }
  9. GraphQLClientͰAPIϦΫΤετ class Session { Session(this._client); final GraphQLClient _client; Future<T> request<T>(Request<T>

    request) async { QueryResult result = await _client.query( QueryOptions( documentNode: gql(request.document), variables: request.variables ?? {}, ) ); return request.parseResponse(result.data); } }
  10. GraphQLClientͰAPIϦΫΤετ class Session { Session(this._client); final GraphQLClient _client; Future<T> request<T>(Request<T>

    request) async { QueryResult result = await _client.query( QueryOptions( documentNode: gql(request.document), variables: request.variables ?? {}, ) ); return request.parseResponse(result.data); } }
  11. GraphQLClientͰAPIϦΫΤετ class Session { Session(this._client); final GraphQLClient _client; Future<T> request<T>(Request<T>

    request) async { QueryResult result = await _client.query( QueryOptions( documentNode: gql(request.document), variables: request.variables ?? {}, ) ); return request.parseResponse(result.data); } }
  12. λΠϜϥΠϯAPIΛ࣮૷͢Δ class TimelineRequest extends Request<List<CheckInEntity>> { String get document =>

    “”” query GetTimeline { timeline { user { name } image_url comment } } “””; List<CheckInEntity> parseResponse(dynamic data) {} }
  13. λΠϜϥΠϯAPIΛ࣮૷͢Δ part 'CheckInEntity.g.dart'; @JsonSerializable() class CheckInEntity { @JsonKey(name: 'user') final

    UserEntity user; @JsonKey(name: 'image_url') final String imageUrl; @JsonKey(name: 'comment') final String comment; factory CheckInEntity.fromJson(Map<String, dynamic> json) => _$CheckInEntity FromJson(json); }
  14. λΠϜϥΠϯAPIΛ࣮૷͢Δ part 'CheckInEntity.g.dart'; @JsonSerializable() class CheckInEntity { @JsonKey(name: 'user') final

    UserEntity user; @JsonKey(name: 'image_url') final String imageUrl; @JsonKey(name: 'comment') final String comment; factory CheckInEntity.fromJson(Map<String, dynamic> json) => _$CheckInEntityFromJson(json); }
  15. λΠϜϥΠϯAPIΛ࣮૷͢Δ class TimelineRequest extends Request<List<CheckInEntity>>{ String get document => /*লུ*/

    List<CheckInEntity> parseResponse(dynamic data) { List<dynamic> timeline = data[‘timeline’]; return timeline.map((tl) => CheckInEntity.fromJson(tl)).toList(); } }
  16. ΫΤϦΛϑϥάϝϯτԽ͢Δ class TimelineRequest extends Request<List<CheckInEntity>> { String get document =>

    “”” query GetTimeline { timeline { user { name } image_url comment } } “””; List<CheckInEntity> parseResponse(dynamic data) {} } ࠶ܝ
  17. ΫΤϦΛϑϥάϝϯτԽ͢Δ class TimelineRequest extends Request<List<CheckInEntity>> { String get document =>

    “”” query GetTimeline { timeline { user { name } image_url comment } } “””; List<CheckInEntity> parseResponse(dynamic data) {} } part 'CheckInEntity.g.dart'; @JsonSerializable() class CheckInEntity { @JsonKey(name: 'user') final UserEntity user; @JsonKey(name: 'image_url') final String imageUrl; @JsonKey(name: 'comment') final String comment; }
  18. ΫΤϦΛϑϥάϝϯτԽ͢Δ class TimelineRequest extends Request<List<CheckInEntity>> { String get document =>

    “”” query GetTimeline { timeline { user { name } image_url comment } } “””; List<CheckInEntity> parseResponse(dynamic data) {} } part 'CheckInEntity.g.dart'; @JsonSerializable() class CheckInEntity { @JsonKey(name: 'user') final UserEntity user; @JsonKey(name: 'image_url') final String imageUrl; @JsonKey(name: 'comment') final String comment; }
  19. ΫΤϦΛϑϥάϝϯτԽ͢Δ { hero { name friend { ...characterFragment } }

    } fragment characterFragment on Character { name }
  20. ΫΤϦΛϑϥάϝϯτԽ͢Δ { hero { name friend { ...characterFragment } }

    } fragment characterFragment on Character { name }
  21. ΫΤϦΛϑϥάϝϯτԽ͢Δ { hero { name friend { ...characterFragment } }

    } fragment characterFragment on Character { name }
  22. ΫΤϦΛϑϥάϝϯτԽ͢Δ class CheckInEntity { /**লུ*/ const String checkInEntityFragmentName = “checkInField";

    const String checkInEntityFragment =''' fragment $checkInEntityFragmentName on checkIn { user { name } image_url comment } } '''; }
  23. ΫΤϦΛϑϥάϝϯτԽ͢Δ class CheckInEntity { /**লུ*/ const String checkInEntityFragmentName = “checkInField";

    const String checkInEntityFragment =''' fragment $checkInEntityFragmentName on checkIn { user { name } image_url comment } } '''; }
  24. ΫΤϦΛϑϥάϝϯτԽ͢Δ class TimelineRequest extends Request<List<CheckInEntity>>{ String get document => “””

    query { timeline { user { name } image_url comment } } “””; List<CheckInEntity> parseResponse(dynamic data) {} }
  25. ΫΤϦΛϑϥάϝϯτԽ͢Δ class TimelineRequest extends Request<List<CheckInEntity>>{ String get document => “””

    query { timeline { ...$checkInEntityFragmentName } } $checkInEntityFragment “””; List<CheckInEntity> parseResponse(dynamic data) {} }
  26. ϑΟʔϧυͱΫΤϦΛ ͍ۙ৔ॴʹஔ͘͜ͱ͕Ͱ͖͕ͨɾɾɾ part 'CheckInEntity.g.dart'; @JsonSerializable() class CheckInEntity { @JsonKey(name: 'user')

    final UserEntity user; @JsonKey(name: 'image_url') final String imageUrl; @JsonKey(name: 'comment') final String comment;
 const String checkInEntityFragmentName = “checkInField"; const String checkInEntityFragment =''' fragment $checkInEntityFragmentName on checkIn { user { name } image_url comment } } '''; }
  27. ϑΟʔϧυ௥Ճ͢Δͷ͸໘౗͍͘͞ part 'CheckInEntity.g.dart'; @JsonSerializable() class CheckInEntity { @JsonKey(name: 'user') final

    UserEntity user; @JsonKey(name: 'image_url') final String imageUrl; @JsonKey(name: 'comment') final String comment;
 @JsonKey(name: 'drink_name') final String drinkName;
 const String checkInEntityFragmentName = “checkInField"; const String checkInEntityFragment =''' fragment $checkInEntityFragmentName on checkIn { user { name } image_url comment drink_name } } '''; } ಉ͡
  28. ΫϥεϑΟʔϧυ͔ΒFragmentΛࣗಈੜ੒͢ΔϓϥάΠϯΛ࡞Γ·͠ ͨɻ part 'CheckInEntity.g.dart'; @JsonSerializable() class CheckInEntity { @JsonKey(name: 'user')

    final UserEntity user; @JsonKey(name: 'image_url') final String imageUrl; @JsonKey(name: 'comment') final String comment;
 @JsonKey(name: 'drink_name') final String drinkName;
 const String checkInEntityFragmentName = “checkInField"; const String checkInEntityFragment =''' fragment $checkInEntityFragmentName on checkIn { user { name } image_url comment drink_name } } '''; }
  29. ΫϥεϑΟʔϧυ͔ΒFragmentΛࣗಈੜ੒͢ΔϓϥάΠϯΛ࡞Γ·͠ ͨɻ part 'CheckInEntity.g.dart'; @JsonSerializable() class CheckInEntity { @JsonKey(name: 'user')

    final UserEntity user; @JsonKey(name: 'image_url') final String imageUrl; @JsonKey(name: 'comment') final String comment;
 @JsonKey(name: 'drink_name') final String drinkName;
 const String checkInEntityFragmentName = “checkInField"; const String checkInEntityFragment =''' fragment $checkInEntityFragmentName on checkIn { user { name } image_url comment drink_name } } '''; }
  30. ΫϥεϑΟʔϧυ͔ΒFragmentΛࣗಈੜ੒͢ΔϓϥάΠϯΛ࡞Γ·͠ ͨɻ part 'CheckInEntity.g.dart'; @JsonSerializable() class CheckInEntity { @JsonKey(name: 'user')

    final UserEntity user; @JsonKey(name: 'image_url') final String imageUrl; @JsonKey(name: 'comment') final String comment;
 @JsonKey(name: 'drink_name') final String drinkName;
 const String checkInEntityFragmentName = “checkInField"; const String checkInEntityFragment =''' fragment $checkInEntityFragmentName on checkIn { user { name } image_url comment drink_name } } '''; }
  31. graphql_fragment_generatorͷ࢖͍ํ part 'CheckInEntity.g.dart'; @JsonSerializable() class CheckInEntity { @JsonKey(name: 'user') final

    UserEntity user; @JsonKey(name: 'image_url') final String imageUrl; @JsonKey(name: 'comment') final String comment;
 @JsonKey(name: 'drink_name') final String drinkName; /**লུ*/ }
  32. graphql_fragment_generatorͷ࢖͍ํ part ‘CheckInEntity.g.dart'; part ‘CheckInEntity.graphql.g.dart’; @GraphQLFragment(on: ‘checkIn’) @JsonSerializable() class CheckInEntity

    { @JsonKey(name: 'user') final UserEntity user; @JsonKey(name: 'image_url') final String imageUrl; @JsonKey(name: 'comment') final String comment;
 @JsonKey(name: 'drink_name') final String drinkName; /**লུ*/ }
  33. graphql_fragment_generatorͷ࢖͍ํ part ‘CheckInEntity.g.dart'; part ‘CheckInEntity.graphql.g.dart’; @GraphQLFragment(on: ‘checkIn’) @JsonSerializable() class CheckInEntity

    { @JsonKey(name: 'user') final UserEntity user; @JsonKey(name: 'image_url') final String imageUrl; @JsonKey(name: 'comment') final String comment;
 @JsonKey(name: 'drink_name') final String drinkName; /**লུ*/ } FragmentͷonͷTypeΛࢦఆ
  34. graphql_fragment_generatorͷ࢖͍ํ part ‘CheckInEntity.g.dart'; part ‘CheckInEntity.graphql.g.dart’; @GraphQLFragment(on: ‘checkIn’) @JsonSerializable() class CheckInEntity

    { @JsonKey(name: 'user') final UserEntity user; @JsonKey(name: 'image_url') final String imageUrl; @JsonKey(name: 'comment') final String comment;
 @JsonKey(name: 'drink_name') final String drinkName; /**লུ*/ }
  35. graphql_fragment_generatorͷ࢖͍ํ const String checkInEntityFragmentName = “checkInField"; const String checkInEntityFragment =

    ''' fragment $checkInEntityFragmentName on checkIn { comment image_url user { ...$userEntityFragmentName } drink_name } $userEntityFragment ''';
  36. graphql_fragment_generatorͷ࢖͍ํ const String checkInEntityFragmentName = "checkInField"; const String checkInEntityFragment =

    ''' fragment $checkInEntityFragmentName on checkIn { user { ...$userEntityFragmentName } image_url comment drink_name } $userEntityFragment '''; class CheckInEntity { /**লུ*/ const String checkInEntityFragmentName = “checkInField"; const String checkInEntityFragment =''' fragment $checkInEntityFragmentName on checkIn { user { name } image_url comment drink_name } } '''; } ࣗಈੜ੒ खಈͰఆٛ
  37. graphql_fragment_generatorͷ࢖͍ํ const String checkInEntityFragmentName = "checkInField"; const String checkInEntityFragment =

    ''' fragment $checkInEntityFragmentName on checkIn { user { ...$userEntityFragmentName } image_url comment drink_name } $userEntityFragment '''; class CheckInEntity { /**লུ*/ const String checkInEntityFragmentName = “checkInField"; const String checkInEntityFragment =''' fragment $checkInEntityFragmentName on checkIn { user { name } image_url comment drink_name } } '''; } ࣗಈੜ੒ खಈͰఆٛ
  38. graphql_fragment_generatorͷ࢖͍ํ @GraphQLFragment(on: 'user') @JsonSerializable() class UserEntity { @JsonKey(name: 'name') final

    String name; /**লུ*/ } @GraphQLFragment(on: ‘checkIn’) @JsonSerializable() class CheckInEntity { @JsonKey(name: 'user') final UserEntity user; /**লུ*/ }
  39. graphql_fragment_generatorͷ࢖͍ํ @GraphQLFragment(on: 'user') @JsonSerializable() class UserEntity { @JsonKey(name: 'name') final

    String name; /**লུ*/ } @GraphQLFragment(on: ‘checkIn’) @JsonSerializable() class CheckInEntity { @JsonKey(name: 'user') final UserEntity user; /**লུ*/ } ࢀর
  40. graphql_fragment_generatorͷ࢖͍ํ @GraphQLFragment(on: 'user') @JsonSerializable() class UserEntity { @JsonKey(name: 'name') final

    String name; /**লུ*/ } const String userEntityFragmentName = "userField"; const String userEntityFragment = ''' fragment $userEntityFragmentName on user { name } '''; @GraphQLFragment(on: ‘checkIn’) @JsonSerializable() class CheckInEntity { @JsonKey(name: 'user') final UserEntity user; /**লུ*/ } const String checkInEntityFragmentName = "checkInField"; const String checkInEntityFragment = ''' fragment $checkInEntityFragmentName on checkIn { user { ...$userEntityFragmentName } image_url comment drink_name } $userEntityFragment '''; ࢀর ࣗಈੜ੒ ࣗಈੜ੒
  41. graphql_fragment_generatorͷ࢖͍ํ @GraphQLFragment(on: 'user') @JsonSerializable() class UserEntity { @JsonKey(name: 'name') final

    String name; /**লུ*/ } const String userEntityFragmentName = "userField"; const String userEntityFragment = ''' fragment $userEntityFragmentName on user { name } '''; @GraphQLFragment(on: ‘checkIn’) @JsonSerializable() class CheckInEntity { @JsonKey(name: 'user') final UserEntity user; /**লུ*/ } const String checkInEntityFragmentName = "checkInField"; const String checkInEntityFragment = ''' fragment $checkInEntityFragmentName on checkIn { user { ...$userEntityFragmentName } image_url comment drink_name } $userEntityFragment '''; ࢀর ࣗಈੜ੒ ࢀর ࣗಈੜ੒