Ger*_*pea 9 dependency-injection flutter
我正在尝试学习如何在 flutter 项目中设置依赖项注入,但我遇到了一个问题:
\nI/flutter (14507): \xe2\x95\x90\xe2\x95\x90\xe2\x95\xa1 EXCEPTION CAUGHT BY WIDGETS LIBRARY \xe2\x95\x9e\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\nI/flutter (14507): The following assertion was thrown building _InheritedProviderScope<NumberTriviaBloc>(value: null):\nI/flutter (14507): No type GetConcreteNumberTrivia is registered inside GetIt.\nI/flutter (14507): Did you forget to pass an instance name?\nI/flutter (14507): (Did you accidentally do GetIt sl=GetIt.instance(); instead of GetIt sl=GetIt.instance;did you\nI/flutter (14507): forget to register it?)\nI/flutter (14507): 'package:get_it/get_it_impl.dart':\nI/flutter (14507): Failed assertion: line 251 pos 14: 'instanceFactory != null'\nI/flutter (14507): \nI/flutter (14507): The relevant error-causing widget was:\nI/flutter (14507): _InheritedProviderScope<NumberTriviaBloc>\nRun Code Online (Sandbox Code Playgroud)\n依赖初始化:
\nfinal sl = GetIt.instance;\n\nvoid init() {\n //! Features - Number Trivia\n //* Bloc\n sl.registerFactory<NumberTriviaBloc>(() => NumberTriviaBloc(concrete: sl(), inputConverter: sl(), random: sl()));\n\n //* Use cases\n sl.registerLazySingleton<UseCase<NumberTrivia, Params>>(() => GetConcreteNumberTrivia(sl()));\n sl.registerLazySingleton<UseCase<NumberTrivia, NoParams>>(() => GetRandomNumberTrivia(sl()));\n\n //* Repository\n sl.registerLazySingleton<NumberTriviaRepository>(() => NumberTriviaRepositoryImplementation(\n localDataSource: sl(), networkInfo: sl(), remoteDataSource: sl()));\n\n //* Data sources\n sl.registerLazySingleton<NumberTriviaRemoteDataSource>(\n () => NumberTriviaRemoteDataSourceImpl(client: sl()));\n\n sl.registerLazySingleton<NumberTriviaLocalDataSource>(\n () => NumberTriviaLocalDataSourceImpl(sharedPreferences: sl()));\n\n //! Core\n sl.registerLazySingleton<InputConverter>(() => InputConverter());\n sl.registerLazySingleton<NetworkInfo>(() => NetworkInfoImpl(sl()));\n\n //! External\n sl.registerLazySingletonAsync<SharedPreferences>(() => SharedPreferences.getInstance());\n sl.registerLazySingleton<http.Client>(() => http.Client());\n sl.registerLazySingleton<DataConnectionChecker>(() => DataConnectionChecker());\n}\nRun Code Online (Sandbox Code Playgroud)\n我不明白问题是什么,这是其他东西初始化的代码:
\nclass NumberTriviaBloc extends Bloc<NumberTriviaEvent, NumberTriviaState> {\n final GetConcreteNumberTrivia getConcreteNumberTrivia;\n final GetRandomNumberTrivia getRandomNumberTrivia;\n final InputConverter inputConverter;\n\n NumberTriviaBloc(\n {@required GetConcreteNumberTrivia concrete,\n @required GetRandomNumberTrivia random,\n @required this.inputConverter})\n : assert(concrete != null),\n assert(random != null),\n assert(inputConverter != null),\n getConcreteNumberTrivia = concrete,\n getRandomNumberTrivia = random;\n ...\n}\n\nclass GetConcreteNumberTrivia implements UseCase<NumberTrivia, Params>{\n final NumberTriviaRepository repository;\n\n GetConcreteNumberTrivia(this.repository);\n\n @override\n Future<Either<Failure, NumberTrivia>> call(Params params) async {\n return await repository.getConcreteNumberTrivia(params.number);\n }\n}\n\nclass GetRandomNumberTrivia implements UseCase<NumberTrivia, NoParams> {\n final NumberTriviaRepository repository;\n\n GetRandomNumberTrivia(this.repository);\n\n @override\n Future<Either<Failure, NumberTrivia>> call(NoParams params) async {\n return await repository.getRandomNumberTrivia();\n }\n}\n\nclass NumberTriviaRepositoryImplementation implements NumberTriviaRepository {\n final NumberTriviaRemoteDataSource remoteDataSource;\n final NumberTriviaLocalDataSource localDataSource;\n final NetworkInfo networkInfo;\n\n NumberTriviaRepositoryImplementation(\n {@required this.remoteDataSource,\n @required this.localDataSource,\n @required this.networkInfo});\n ...\n}\n\nclass NumberTriviaRemoteDataSourceImpl implements NumberTriviaRemoteDataSource {\n final http.Client client;\n\n NumberTriviaRemoteDataSourceImpl({@required this.client});\n ...\n}\n\nclass NumberTriviaLocalDataSourceImpl implements NumberTriviaLocalDataSource {\n final SharedPreferences sharedPreferences;\n\n NumberTriviaLocalDataSourceImpl({@required this.sharedPreferences});\n ...\n}\n\nclass InputConverter {}\n\nclass NetworkInfoImpl extends NetworkInfo {\n final DataConnectionChecker connectionChecker;\n\n NetworkInfoImpl(this.connectionChecker);\n ...\n}\nRun Code Online (Sandbox Code Playgroud)\n小部件是:
\nvoid main() {\n di.init();\n runApp(MyApp());\n}\n\nclass MyApp extends StatelessWidget {\n @override\n Widget build(BuildContext context) {\n return MaterialApp(\n title: 'Flutter Demo',\n theme: ThemeData(\n primaryColor: Colors.green.shade800,\n accentColor: Colors.green.shade600,\n ),\n home: NumberTriviaPage(),\n );\n }\n}\n\nclass NumberTriviaPage extends StatelessWidget {\n @override\n Widget build(BuildContext context) {\n return Scaffold(\n appBar: AppBar(\n title: Text('Number Trivia'),\n ),\n body: SingleChildScrollView(child: buildBody(context)),\n );\n }\n\n BlocProvider<NumberTriviaBloc> buildBody(BuildContext context) {\n return BlocProvider<NumberTriviaBloc>(\n create: (_) => sl<NumberTriviaBloc>(),\n child: Center(\n child: Padding(\n padding: const EdgeInsets.all(10),\n child: Column(\n children: <Widget>[\n SizedBox(\n height: 10,\n ),\n BlocBuilder<NumberTriviaBloc, NumberTriviaState>(\n // ignore: missing_return\n builder: (context, state) {\n if (state is Empty) {\n return MessageDisplay(\n message: 'Start searching',\n );\n } else if (state is Loading) {\n return LoadingWidget();\n } else if (state is Loaded) {\n return TriviaDisplay(\n numberTrivia: state.trivia,\n );\n } else if (state is Error) {\n return MessageDisplay(\n message: state.message,\n );\n }\n },\n ),\n SizedBox(\n height: 20,\n ),\n TriviaControl()\n ],\n ),\n ),\n ),\n );\n }\n}\nRun Code Online (Sandbox Code Playgroud)\n我不明白为什么这对我不起作用。\n我按照 youtube 上的教程进行操作,还检查了 github 存储库上本教程中的代码,但这对我没有帮助。\n那么你能向我解释一下发生了什么吗?
\n在 tnc1997 答案的帮助下,我收到了一个新错误:
\nlib/injection_container.dart:27:91: Error: The argument type 'NumberTriviaRepository/*1*/' can't be assigned to the parameter type 'NumberTriviaRepository/*2*/'.\n - 'NumberTriviaRepository/*1*/' is from 'package:clean_architecture/features/number_trivia/domain/repositories/number_trivia_repository.dart' ('lib/features/number_trivia/domain/repositories/number_trivia_repository.dart').\n - 'NumberTriviaRepository/*2*/' is from 'lib/features/number_trivia/domain/repositories/number_trivia_repository.dart'.\n sl.registerLazySingleton<UseCase<NumberTrivia, NoParams>>(() => GetRandomNumberTrivia(sl<NumberTriviaRepository>()));\nRun Code Online (Sandbox Code Playgroud)\n这是同一个文件,下面一行使用类似的合同
\n//* Use cases\n sl.registerLazySingleton<UseCase<NumberTrivia, Params>>(() => GetConcreteNumberTrivia(sl<NumberTriviaRepository>()));\n sl.registerLazySingleton<UseCase<NumberTrivia, NoParams>>(() => GetRandomNumberTrivia(sl<NumberTriviaRepository>()));\n\n //* Repository\n sl.registerLazySingleton<NumberTriviaRepository>(() => NumberTriviaRepositoryImplementation(\n localDataSource: sl<NumberTriviaLocalDataSource>(), networkInfo: sl<NetworkInfo>(), remoteDataSource: sl<NumberTriviaRemoteDataSource>()));\nRun Code Online (Sandbox Code Playgroud)\n现在我比以前更困惑了
\n我非常确定,在使用该GetIt包时,您需要依赖于接口,而不是构造函数中的具体类型。毕竟,依赖注入的原则之一是依赖接口而不是实现,从而允许您轻松切换实现。我在下面添加了一个代码示例,展示了如何完成此操作。如果您还没有这样做,您可能需要查看此处的文档以获取更多信息和代码示例。如果您对代码示例有任何问题,请随时发表评论!
class NumberTriviaBloc extends Bloc<NumberTriviaEvent, NumberTriviaState> {
final UseCase<NumberTrivia, Params> getConcreteNumberTrivia;
final UseCase<NumberTrivia, NoParams> getRandomNumberTrivia;
final InputConverter inputConverter;
NumberTriviaBloc(
{@required UseCase<NumberTrivia, Params> concrete,
@required UseCase<NumberTrivia, NoParams> random,
@required this.inputConverter})
: assert(concrete != null),
assert(random != null),
assert(inputConverter != null),
getConcreteNumberTrivia = concrete,
getRandomNumberTrivia = random;
...
}
Run Code Online (Sandbox Code Playgroud)
sl.registerFactory<NumberTriviaBloc>(() => NumberTriviaBloc(concrete: sl<UseCase<NumberTrivia, Params>>(), inputConverter: sl<InputConverter>(), random: sl<UseCase<NumberTrivia, NoParams>>()));
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
13735 次 |
| 最近记录: |