Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

_InternalLinkedHashMap<dynamic, dynamic> is not a subtype of Map<String, dynamic>? in type cast #1091

Closed
moehmeni opened this issue Apr 2, 2022 · 11 comments · Fixed by #1093 or #1167
Assignees

Comments

@moehmeni
Copy link

moehmeni commented Apr 2, 2022

This is the error when I try to run client.query with a GraphQLConsumer for onChanged event of a TextField

Unhandled Exception: type '_InternalLinkedHashMap<dynamic, dynamic>' is not a subtype of type 'Map<String, dynamic>?' in type cast

seems there is an issue during encoding/decoding the API result into the Hive box
(it's weird it was working as expected yesterday while I did not change the code and today it has issues)

Expected behavior
Get the result from client.query and update the view (using a Getx controller since Query was not working as expected)

device / execution context
Android simulator

The event function:

  void onInputChange(String value, GraphQLClient client, SearchController _) {
    if (value.isEmpty) {
      _.changeQuery("");
      return;
    }
    client
        .query(
      QueryOptions(document: gql(searchArtistQuery), variables: {
        'q': value,
      }),
    )
        .then((QueryResult result) {
      if (result.data == null) return;
      final artists = (result.data?['searchArtists'] ?? [])
          .map((artist) => Artist.fromJson(artist))
          .toList();
      if (artists.isEmpty) return;
      _.changeQuery(value);
      _.changeResult(artists);
    });
  }
Stacktrace:
E/flutter (23039): [ERROR:flutter/lib/ui/ui_dart_state.cc(209)] Unhandled Exception: type '_InternalLinkedHashMap<dynamic, dynamic>' is not a subtype of type 'Map<String, dynamic>?' in type cast
E/flutter (23039): #0      BoxImpl.get
package:hive//box/box_impl.dart:44
E/flutter (23039): #1      HiveStore.get
package:graphql//cache/hive_store.dart:51
E/flutter (23039): #2      GraphQLCache.readNormalized
package:graphql//cache/cache.dart:114
E/flutter (23039): #3      NormalizingDataProxy.readQuery.<anonymous closure>
package:graphql//cache/_normalizing_data_proxy.dart:87
E/flutter (23039): #4      denormalizeOperation
package:normalize/src/denormalize_operation.dart:63
E/flutter (23039): #5      NormalizingDataProxy.readQuery
package:graphql//cache/_normalizing_data_proxy.dart:85
E/flutter (23039): #6      QueryManager.maybeRebroadcastQueries
package:graphql//core/query_manager.dart:473
E/flutter (23039): #7      QueryManager.query
package:graphql//core/query_manager.dart:164
E/flutter (23039): <asynchronous suspension>
E/flutter (23039): #8      GraphQLClient.query
package:graphql/src/graphql_client.dart:152
E/flutter (23039): <asynchronous suspension>
E/flutter (23039):
@budde377 budde377 self-assigned this Apr 2, 2022
@budde377
Copy link
Collaborator

budde377 commented Apr 3, 2022

@mdmomeni Thanks for reporting this! Do you mind sharing how you're initializing the client? Specifically, how are you providing the Hive box to the client.

@moehmeni
Copy link
Author

moehmeni commented Apr 3, 2022

My main function:

void main() async {
  WidgetsFlutterBinding.ensureInitialized();

  // Initialize Firebase
  await FCM.init();

  // Initialize Hive (from GraphQL package)
  await initHiveForFlutter();

  // Initialize UserController Hive box
  await UserController.init(); // await Hive.openBox<String>("user");

  // GraphQL
  final HttpLink httpLink = HttpLink(
    "http://10.0.2.2:8000/graphql",
  );

  final AuthLink authLink = AuthLink(
    getToken: () => UserController.token,
  );

  final Link link = authLink.concat(httpLink);

  ValueNotifier<GraphQLClient> client = ValueNotifier(
    GraphQLClient(
      link: link,
      cache: GraphQLCache(store: HiveStore()),
    ),
  );
  runApp(MyApp(client));
}

Also MyApp:

class MyApp extends StatelessWidget {
  const MyApp(this.client, {Key? key}) : super(key: key);
  final ValueNotifier<GraphQLClient> client;

  @override
  Widget build(BuildContext context) {
    return GraphQLProvider(
      client: client,
      child: GetMaterialApp(
...

Client provider:

GetBuilder<SearchController>(
              init: SearchController(),
              builder: (_) {
                return GraphQLConsumer(builder: (client) {
                  return Expanded(
                      child: Column(children: [
                    searchField(client, _),
                    const SizedBox(height: 10),
                    Expanded(
                        child: Stack(
                      alignment: Alignment.center,
                      children: [mainBody(_), submitBtn()],
                    ))
                  ]));
                });
              }),
...

  Widget searchField(GraphQLClient client, SearchController _) {
    return Padding(
      padding: const EdgeInsets.all(10),
      child: TextField(
        textDirection: TextDirection.ltr,
        decoration: CInputDecoration(hintText: "جستجو"),
        onChanged: (q) => onInputChange(q, client, _),
      ),
    );
  }

@budde377
Copy link
Collaborator

budde377 commented Apr 3, 2022

Cheers @mdmomeni! I've created a PR with a fix. If you're able to verify that it's working for you, that'd be a huge help!

@moehmeni
Copy link
Author

moehmeni commented Apr 3, 2022

Thank you, but how can I replace the updated code? and should I review the PR or something after testing it?

@budde377
Copy link
Collaborator

budde377 commented Apr 3, 2022

@mdmomeni

You should be able to add the branch as a dependency directly. I.e., update your pubspec.yaml file with

  graphql_flutter:
    git:
      url: git://github.com/zino-hofmann/graphql-flutter.git
      ref: fix-hive
      path: packages/graphql_flutter

I'm not sure if you can add a review, but a comment on the PR (or here) will be fine.

@Adherentman
Copy link

Adherentman commented Jun 27, 2022

@mdmomeni

You should be able to add the branch as a dependency directly. I.e., update your pubspec.yaml file with

  graphql_flutter:
    git:
      url: git://github.com/zino-hofmann/graphql-flutter.git
      ref: fix-hive
      path: packages/graphql_flutter

I'm not sure if you can add a review, but a comment on the PR (or here) will be fine.

@budde377
The exception still exists.
When I set fetchPolicy to FetchPolicy.networkOnly, this problem does not exist.
But I set it to FetchPolicy.cacheAndNetwork, and this exception occurred. I guess that the data type stored in hive does not match the Map.

This is my data structure:

[
  {
    _id: 6141e5e09fa3f5afd79e6ecb,
    type: urlLaunch,
    content:
      {
        image: image1.png,
        url: https://example1.com,
      },
    __typename: Recommend,
  },
  {
    _id: 6141e8029fa3f5afd79e6ecc,
    type: urlLaunch,
    content:
      {
        image: image.png,
        url: https://example.com,
      },
    __typename: Recommend,
  },
]

I use fast_immutable_collections and freezed

@freezed
class Recommend with _$Recommend {
  factory Recommend({
    required String type,
    required IMap<String, String> content,
  }) = _Recommend;
  factory Recommend.fromJson(Map<String, dynamic> json) =>
      _$RecommendFromJson(json);
}

void exampleQuery () {
  final result =
      await client.query$Recommend(Options$Query$Recommend(
    operationName: 'exampleQuery',
    fetchPolicy: FetchPolicy.cacheAndNetwork,
    variables: Variables$Query$Recommend(
      memberId: memberId,
    ),
  ));

  if (result.hasException) {
    handleException(result);
    throw Exception(result.exception.toString());
  }
    final recommendList = IList.fromJson(
     ///  🔨 If I want to not report this exception, I need to do the following
     /// FIX: should work code json.decode(json.encode(result.data?["exampleQuery"]))
      result.data?["exampleQuery"], 

      (dynamic item) => Recommend.fromJson(item),
    );
  return recommendList;
}

@budde377
Copy link
Collaborator

Thanks for reporting. Please check if #1167 fixes this for you! @Adherentman

@Adherentman
Copy link

Thanks for reporting. Please check if #1167 fixes this for you! @Adherentman

@budde377
I checked the relevant code and it should solve the problem。
But I have a problem trying to use the latest code in pubspec.yaml.

graphql:
    git:
      url: https://github.com/zino-hofmann/graphql-flutter.git
      ref: main
      path: packages/graphql
  graphql_flutter:
    git:
      url: https://github.com/zino-hofmann/graphql-flutter.git
      ref: main
      path: packages/graphql_flutter

get error:

Because every version of graphql_flutter from git depends on graphql from hosted and example_app depends on graphql from git, graphql_flutter from git is forbidden.
So, because example_app depends on graphql_flutter from git, version solving failed.
pub get failed (1; So, because example_app depends on graphql_flutter from git, version solving failed.)

Or when will it be published on pub.dev

@vincenzopalazzo
Copy link
Collaborator

this is your error, you should put also inside the override package the graphql, this tell to pub "Hey you are using git, but there is some depenciences in common, so ignore it and use git".

It is strange, but the dependieces resolution world is more strange.

BTW I'm releasing the new beta release later in the day

@Adherentman
Copy link

I have used main branch to verify that it runs very well. Thank you.

@vincenzopalazzo
Copy link
Collaborator

@Adherentman the new beta is out

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
4 participants