我面临着这个非常奇怪和原始的问题,我试图弄清楚但无法解决。
我按照以下方式设计了一个抽象类
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 方法来获取注入的对象,我就会收到异常。 有人可以指出,如果我在这里遗漏了什么吗??
声明提供者时,删除创建函数中的返回类型:
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();
}
尝试了同样的方法,并能够按预期获得提供商的价值。
经过深入研究,我找到了一个解决方案,可能会对遇到类似问题的其他人有所帮助。
provider 包提供了两种创建provider 的方法:
需要注意的是,第一种方法缺乏抽象支持。尝试直接从上下文访问T将导致异常。这是因为提供的对象将代表 T 的 implementation,而不是 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();
}