与泛型和抽象一起使用时出现 ProviderNotFound 异常

问题描述 投票:0回答:2

我面临着这个非常奇怪和原始的问题,我试图弄清楚但无法解决。

我按照以下方式设计了一个抽象类

abstract class BaseStatelessWidget<T extends BaseStore> extends StatelessWidget
    with RouteAware {
  late final T childStore;

  BaseStatelessWidget({super.key});

  @override
  Widget build(BuildContext context) {
    childStore = getImplementedStore();
    return Provider(
      create: <T>(_) => childStore,
      builder: (ctx, __) {
        final store = Provider.of<T>(ctx, listen: false); // <== I'm getting error here for providerNotFound excepton
        store;
        return _BaseStatefulWidget<T>(
          builder: buildScreen,
        );
      },
    );
  }

  Widget buildScreen(BuildContext context);

  T getImplementedStore();
}

这是我实现上述抽象类的方式,

class Counter extends BaseStatelessWidget<CounterStore> {
  Counter({super.key});

  @override
  Widget buildScreen(BuildContext context) {
    return Scaffold(
      body: Container(
        color: AppColors.white,
        child: Column(
          children: [
            Observer(
              builder: (ctx) {
                return Text(
                  '${getStore<CounterStore>(ctx).counter} Times Clicked',
                );
              },
            )
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () {
          getStore<CounterStore>(context).increment();
        },
        child: const Icon(Icons.add),
      ),
    );
  }

  @override
  CounterStore getImplementedStore() {
    return getIt<CounterStore>();
  }
}

T getStore<T extends BaseStore>(BuildContext context) {
  return Provider.of<T>(context, listen: false);
}

一旦我调用 Provider.of 方法来获取注入的对象,我就会收到异常。 有人可以指出,如果我在这里遗漏了什么吗??

flutter dart provider
2个回答
0
投票

声明提供者时,删除创建函数中的返回类型:

    abstract class BaseStatelessWidget<T extends BaseStore> extends StatelessWidget with RouteAware {
  late final T childStore;

  BaseStatelessWidget({super.key});

  @override
  Widget build(BuildContext context) {
    childStore = getImplementedStore();
    return Provider(
      create: (_) => childStore,//Drop the return type
      builder: (ctx, __) {
        final store = Provider.of<T>(ctx, listen: false);
        return Text(store.value());
      },
    );
  }

  T getImplementedStore();
}

尝试了同样的方法,并能够按预期获得提供商的价值。


0
投票

经过深入研究,我找到了一个解决方案,可能会对遇到类似问题的其他人有所帮助。

provider 包提供了两种创建provider 的方法:

  • 使用提供程序(create: (context) => TExtends())
  • 利用 Provider.value(value: TExtends())。

需要注意的是,第一种方法缺乏抽象支持。尝试直接从上下文访问T将导致异常。这是因为提供的对象将代表 Timplementation,而不是 T 本身。

如果您的目标是获取 T 而不是 TExtends 的实例,我建议选择第二种方法。这将使您解决问题。

这是一个示例实现:

abstract class BaseStatelessWidget<T extends BaseStore> extends StatelessWidget
    with RouteAware {
  late final T childStore;

  BaseStatelessWidget({super.key});

  @override
  Widget build(BuildContext context) {
    childStore = getImplementedStore();
    return Provider<T>.value( // <== This will solve the issue
      value: childStore,
      builder: (ctx, __) {
        final store = Provider.of<T>(ctx, listen: false); // You'll get instance of T, instead of childStore's instance
        store;
        return _BaseStatefulWidget<T>(
          builder: buildScreen,
        );
      },
    );
  }

  Widget buildScreen(BuildContext context);

  T getImplementedStore();
}
© www.soinside.com 2019 - 2024. All rights reserved.