0

ウィジェットがジェネリックの子であり、それ自体がジェネリックであるかどうかinheritFromWidgetOfExactTypeをメソッドが見つけられないようです。InheritedWidgetStatefulWidget

ブロックパターンを実装するために InheritedWidget を使用しています。BlocProvider の初期実装は次のようになります。

class BlocProvider<T extends BlocBase> extends InheritedWidget {
  final T bloc;

  const BlocProvider({
    Key key,
    @required this.bloc,
    @required Widget child,
  })
      : assert(bloc != null),
        assert(child != null),
        super(key: key, child: child);

  static T of<T extends BlocBase>(BuildContext context) {
    final type = _typeOf<BlocProvider<T>>();
    final provider = context.inheritFromWidgetOfExactType(type) as BlocProvider<T>;
    print("provider: $provider");
    return provider.bloc;
  }

  static Type _typeOf<T>() => T;

  @override
  bool updateShouldNotify(BlocProvider old) => false;
}

直接使用すると問題なく動作します:

  @override
  Widget build(BuildContext context) {
    return BlocProvider(
      bloc: BlocTop(),
      child: BlocConsumer()
    );
  }

しかし、ウィジェットツリーが再構築されるたびにブロックの状態が再構築されないように、ブロックプロバイダーを StatefulWidget でラップしたいと思います。

class BlocHolder<T extends BlocBase> extends StatefulWidget { 

final Widget child;
  final T Function() createBloc;
  final bool wantKeepAlive;

  BlocHolder({
    @required this.child,
    this.createBloc,
    this.wantKeepAlive
  });

  @override
  _BlocHolderState createState() => _BlocHolderState();
}

class _BlocHolderState<T extends BlocBase>
    extends State<BlocHolder>
    with AutomaticKeepAliveClientMixin<BlocHolder> {

  T _bloc;

  @override
  void initState() {
    super.initState();
    _bloc = widget.createBloc();
  }

  @override
  Widget build(BuildContext context) {
    return BlocProvider(
      child: widget.child,
      bloc: _bloc,
    );
  }

  @override
  void dispose() {
    _bloc?.dispose();
    super.dispose();
  }

  @override
  bool get wantKeepAlive => widget.wantKeepAlive ?? false;
}

ここで、 InheritedWidget の代わりにこのパターンを使用しようとすると、次のようにinheritFromWidgetOfExactType返されます。null

@override
Widget build(BuildContext context) {
    return BlocHolder(
      createBloc: () => BlocTop(),
      child: BlocConsumer()
    );
  }

この問題を克服する方法はありますか? このアプローチを使用してブロックプロバイダーをネストできるようにしたいことに注意してください。

4

1 に答える 1