Can't initialized GraphQl Client in flutter using Get_it

Viewed 556

I want to implement GraphQL client in my flutter app. For Dependency injection, I use GetIt library. But when I run the app, it says

'Invalid argument (Object of type HomeGraphQLService is not registered inside GetIt. Did you forget to pass an instance name? (Did you accidentally do GetIt sl=GetIt.instance(); instead of GetIt sl=GetIt.instance;)): HomeGraphQLService'

.

It means GraphQL client did not instantiate somehow, although I registered it in my service locator

Session.dart

abstract class Session {
  String getAccessToken();
}

SessionImpl.dart

class SessionImpl extends Session {
  SharedPreferences sharedPref;

  SessionImpl(SharedPreferences sharedPref) {
    this.sharedPref = sharedPref;
  }

  @override
  String getAccessToken() {
    return sharedPref.getString('access_token') ?? "";
  }

}

GraphQLClientGenerator.dart

class GraphQLClientGenerator {
  Session session;

  GraphQLClientGenerator(Session session) {
    this.session = session;
  }

  GraphQLClient getClient() {
    final HttpLink httpLink = HttpLink('https://xxx/graphql');
    final AuthLink authLink = AuthLink(getToken: () async => 'Bearer ${_getAccessToken()}');
    final Link link = authLink.concat(httpLink);

    return GraphQLClient(link: link, cache: GraphQLCache(store: InMemoryStore()));
  }

  String _getAccessToken() {
    return session.getAccessToken();
  }
}

HomeRepository.dart

abstract class HomeRepository {
  Future<List<Course>> getAllCourseOf(String className, String groupName);
}

HomeRepositoryImpl.dart

class HomeRepositoryImpl extends HomeRepository {

  HomeGraphQLService homeGraphQLService;
  HomeMapper homeMapper;

  HomeRepositoryImpl(HomeGraphQLService homeGraphQLService, HomeMapper homeMapper) {
    this.homeGraphQLService = homeGraphQLService;
    this.homeMapper = homeMapper;
  }

  @override
  Future<List<Course>> getAllCourseOf(String className, String groupName) async {
    final response = await homeGraphQLService.getAllCourseOf(className, groupName);
    return homeMapper.toCourses(response).where((course) => course.isAvailable);
  }

}

HomeGraphQLService.dart

class HomeGraphQLService {
  GraphQLClient graphQLClient;

  HomeGraphQLService(GraphQLClient graphQLClient) {
    this.graphQLClient = graphQLClient;
  }

  Future<SubjectResponse> getAllCourseOf(String className, String groupName) async {
    try {
      final response = await graphQLClient.query(getAllCourseQuery(className, groupName));
      return SubjectResponse.fromJson((response.data));
    }  catch (e) {
      return Future.error(e);
    }
  }
}

GraphQuery.dart

QueryOptions getAllCourseQuery(String className, String groupName) {
  String query = """
    query GetSubject($className: String, $groupName: String) {
      subjects(class: $className, group: $groupName) {
        code
        display
        insights {
          coming_soon
          purchased
        }
      }
    }
    """;

  return QueryOptions(
    document: gql(query),
    variables: <String, dynamic>{
      'className': className,
      'groupName': groupName,
    },
  );
}

ServiceLocator.dart

final serviceLocator = GetIt.instance;

Future<void> initDependencies() async {
  await _initSharedPref();
  _initSession();
  _initGraphQLClient();
  _initGraphQLService();
  _initMapper();
  _initRepository();
}

Future<void> _initSharedPref() async {
  SharedPreferences sharedPref = await SharedPreferences.getInstance();
  serviceLocator.registerSingleton<SharedPreferences>(sharedPref);
}

void _initSession() {
  serviceLocator.registerLazySingleton<Session>(()=>SessionImpl(serviceLocator()));
}

void _initGraphQLClient() {
  serviceLocator.registerLazySingleton<GraphQLClient>(() => GraphQLClientGenerator(serviceLocator()).getClient());
}

void _initGraphQLService() {
  serviceLocator.registerLazySingleton<HomeGraphQLService>(() => HomeGraphQLService(serviceLocator()));
}

void _initMapper() {
  serviceLocator.registerLazySingleton<HomeMapper>(() => HomeMapper());
}

void _initRepository() {
  serviceLocator.registerLazySingleton<HomeRepository>(() => HomeRepositoryImpl(serviceLocator(), serviceLocator()));
}

main.dart

Future<void> main() async {
  WidgetsFlutterBinding.ensureInitialized();

  SystemChrome.setPreferredOrientations(
    [DeviceOrientation.portraitUp, DeviceOrientation.portraitDown],
  );
  
  await initDependencies();

  runApp(MyApp());
}
1 Answers

I cannot say where exactly it is happening because it is elsewhere in your code where you are accessing the GraphQLService, but the problem is definitely due to the lazy loading. The object has not been created and loaded by the locator before it is being accessed. Try updating ServiceLocator.dart to instantiate the classes during registration, like so:

void _initSession() {
  serviceLocator.registerSingleton<Session>.(SessionImpl(serviceLocator()));
}

void _initGraphQLClient() {
  serviceLocator.registerSingleton<GraphQLClient>(
    GraphQLClientGenerator(serviceLocator()).getClient());
}

void _initGraphQLService() {
  serviceLocator.registerSingleton<HomeGraphQLService>(
    HomeGraphQLService(serviceLocator()));
}

void _initMapper() {
  serviceLocator.registerSingleton<HomeMapper>(HomeMapper());
}

void _initRepository() {
  serviceLocator.registerSingleton<HomeRepository>(
    HomeRepositoryImpl(serviceLocator(), serviceLocator()));
}
Related