如何在flutter tree控件中使用特定级别的MultiBlocProvider?

yi0zb3m4  于 2023-02-09  发布在  Flutter
关注(0)|答案(1)|浏览(172)

我想使用MultiBlocProvider,如下所示。

如何在flutter tree控件中使用特定级别的MultiBlocProvider?
换句话说,当我们在MaterialApptop上使用MultiBlocProvideron时,没有任何问题,但是根据下面的代码,这个项目会得到一个错误。
示例:

void main() {
  runApp(MaterialApp(
    onGenerateRoute: (settings) {
      switch (settings.name) {
        case "/":
          return MaterialPageRoute(
              builder: (_) => MultiBlocProvider(providers: [
                    BlocProvider(
                      create: (_) => CounterBloc(),
                    )
                  ], child: const GroupA()),
              settings: settings);
        case "/ScopeA":
          return MaterialPageRoute(
              builder: (_) => const ScopeA(), settings: settings);
        default:
          return MaterialPageRoute(
              builder: (_) => const Text("ERROR"), settings: settings);
      }
    },
  ));
}

class GroupA extends StatelessWidget {
  const GroupA({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Group A:')),
      body: Center(
        child: MaterialButton(
            onPressed: () => Navigator.pushNamed(context, '/ScopeA'),
            child: const Text("Go To Scope A")),
      ),
    );
  }
}

class ScopeA extends StatelessWidget {
  const ScopeA({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Scope A:')),
      body: Center(
        child: BlocBuilder<CounterBloc, int>(
          builder: (context, count) {
            return Text(
              '$count',
              style: Theme.of(context).textTheme.displayLarge,
            );
          },
        ),
      ),
    );
  }
}

abstract class CounterEvent {}

class CounterIncrementPressed extends CounterEvent {}

class CounterDecrementPressed extends CounterEvent {}

class CounterBloc extends Bloc<CounterEvent, int> {
  CounterBloc() : super(0) {
    on<CounterIncrementPressed>((event, emit) => emit(state + 1));
    on<CounterDecrementPressed>((event, emit) => emit(state - 1));
  }
}

i使用以下版本: Flutter 阻塞:8.1.2区块:8.1.1
错误:
错误:无法点击测试从未布局过的渲染框。

np8igboo

np8igboo1#

您误解了通过子树和Navigator小部件传递块背后的概念。
基本上,MultiBlocProviderBlocProvider使得块在所有子树中可访问,因此该块将仅在GroupA的窗口小部件子树中可用,通过调用Navigator.pushNamed(),所发生的是另一个分离的子树将被放入Navigator子树中,因此此时GroupAScopeA将不在同一窗口小部件树中,即使当你在Flutter UI上看到一个页面路由设置在其他页面路由之上时,我也可以这样表示它:

-> MultiBlocProvider -> GroupA 
Navigator => | 
               -> ScopeA

正如你所总结的,在GroupA中可用的块在ScopeA中将不可用,除非你以某种方式传递它,比如使用BlocProvider.value()

case "/ScopeA":
          return MaterialPageRoute(
              builder: (context) {
               return BlocProvider.value(
                 value: context.read<CounterBloc>(),
                 child: const ScopeA(),
               );  
              },
            settings: settings,
          );

或者让区块可以通过整个应用访问,这样你就有了一个Flutter树:

-> GroupA 
MultiBlocProvider -> Navigator => | 
                                    -> ScopeA

相关问题