由于上下文问题,无法从子类访问 bloc?

Posted

技术标签:

【中文标题】由于上下文问题,无法从子类访问 bloc?【英文标题】:Cannot access bloc from a child class due to context issues? 【发布时间】:2019-12-16 22:22:27 【问题描述】:

当我尝试从子类访问 bloc 时,它给了我一个错误

flutter: ══╡ EXCEPTION CAUGHT BY WIDGETS LIBRARY ╞═══════════════════════════════════════════════════════════
flutter: The following assertion was thrown building Builder:
flutter:         BlocProvider.of() called with a context that does not contain a Bloc of type
flutter: TopRatedMovieBloc.
flutter:         No ancestor could be found starting from the context that was passed to
flutter: BlocProvider.of<TopRatedMovieBloc>().
flutter:
flutter:         This can happen if:
flutter:         1. The context you used comes from a widget above the BlocProvider.
flutter:         2. You used MultiBlocProvider and didn't explicity provide the BlocProvider types.
flutter:
flutter:         Good: BlocProvider<TopRatedMovieBloc>(builder: (context) => TopRatedMovieBloc())
flutter:         Bad: BlocProvider(builder: (context) => TopRatedMovieBloc()).

我的代码如下所示:

**main.dart**

void main() 
  final MovieRepository movieRepository = MovieRepository(
    movieApiClient: MovieApiClient(
      httpClient: http.Client(),
    ),
  );
  BlocSupervisor.delegate = SimpleBlocDelegate();
  runApp(App(movieRepository: movieRepository),
    );
  

class App extends StatelessWidget 
  final MovieRepository movieRepository;
  App(Key key, @required this.movieRepository)
      : assert(movieRepository != null),
        super(key: key);

  @override
  Widget build(BuildContext context) 
    return MaterialApp(
      title: 'Flutter Infinite Scroll',
      debugShowCheckedModeBanner: false,
      theme: ThemeData(
          primarySwatch: Colors.blue, canvasColor: Colors.transparent),
home: MyHomePage(),
    );
  

class MyHomePage extends StatefulWidget 
  @override
  _MyHomePageState createState() => _MyHomePageState();


class _MyHomePageState extends State<MyHomePage> 
  final GlobalKey<ScaffoldState> _scaffoldKey = new GlobalKey<ScaffoldState>();
  final MovieRepository movieRepository = MovieRepository(
    movieApiClient: MovieApiClient(
      httpClient: http.Client(),
    ),
  );

  @override
  Widget build(BuildContext context) 
    return BlocBuilder<ChangeThemeBloc, ChangeThemeState>(
      builder: (context, state) 
        return Scaffold(body: Container(
            color: state.themeData.primaryColor,
            child: ListView(
              physics: BouncingScrollPhysics(),
              children: <Widget>[
                DiscoverMovies(
                  themeData: state.themeData,
                ),
                BlocProvider(
                  builder: (BuildContext context) =>
                      TopRatedMovieBloc(movieRepository: movieRepository),
                  child: ScrollingMovies(
                    themeData: state.themeData,
                    title: 'Top Rated',
                    api: Api.toprated,
                  ),
                ),
],
            ),
          ),
        );
      ,
    );
  




class ScrollingMovies extends StatefulWidget 
  final ThemeData themeData;
  final String title;
  final Api api;
  ScrollingMovies(
    this.themeData,
    this.api,
    this.title,
  );
  @override
  _ScrollingMoviesState createState() => _ScrollingMoviesState();


class _ScrollingMoviesState extends State<ScrollingMovies> 
  @override
  void initState() 
    super.initState();
    TopRatedMovieBloc _topRatedMovieBloc =
        BlocProvider.of<TopRatedMovieBloc>(context);
  

  @override
  Widget build(BuildContext context) 
    return Column(
      children: <Widget>[])
  

这行给了我错误:

TopRatedMovieBloc _topRatedMovieBloc = BlocProvider.of&lt;TopRatedMovieBloc&gt;(context);

谁能帮我理解这个问题?

【问题讨论】:

【参考方案1】:

您无法在initState 中访问context。 您在这里有一些选择: 1. 将 bloc 用法移到build 方法中。 2.覆盖didChangeDependencies并在那里使用它。第一次在initState 之后调用它,但context 可用。如果依赖项发生变化,它可能会被多次调用,因此如果您只想做一次某事 - 请检查您之前是否没有做过。 3. 通过构造函数传递块

原始错误消息中描述了另一个问题:

flutter:         Good: BlocProvider<TopRatedMovieBloc>(builder: (context) => TopRatedMovieBloc())
flutter:         Bad: BlocProvider(builder: (context) => TopRatedMovieBloc()).

你需要更新_MyHomePageStatebuild方法中的代码,将类型参数添加到BlocProvider,所以它应该看起来像

BlocProvider<TopRatedMovieBloc>(
                  builder: (BuildContext context) =>
                      TopRatedMovieBloc(movieRepository: movieRepository),
                  child: ScrollingMovies(
                    themeData: state.themeData,
                    title: 'Top Rated',
                    api: Api.toprated,
                  ),
                ),

【讨论】:

我将所有 bloc 用法移至 build 方法,但它仍然给我同样的错误? @user818455 我已经用其他问题解决方案更新了我的答案 将 type 参数添加到 BlocProvider 解决了这个问题。谢谢

以上是关于由于上下文问题,无法从子类访问 bloc?的主要内容,如果未能解决你的问题,请参考以下文章

使用 BLoC 的 Flutter 导航:用于从 Navigator 推送路由的上下文必须是 Navigator 小部件的后代

使用不包含 Bloc 类型的上下文调用 Flutter BlocProvider.of()

Flutter / BLoC - 使用不包含 ArticlesBloc 类型的 Bloc 的上下文调用 BlocProvider.of()

使用不包含 Bloc 类型的上下文调用 Flutter BLoC BlocProvider.of()

BlocProvider.of() 使用不包含 Bloc<dynamic,dynamic> 类型的 Bloc 的上下文调用

Flutter Bloc:在创建的上下文中没有我的 bloc 的祖先,而我很好地为其提供了 BlocProvider.value