热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

如何使用提供程序在Flutter视图中获取提供程序值?

我正在按照

我正在按照this tutorial中描述的模式,使用Provider(3.1.0)中的MultiProvider构建一个flutter应用程序。

在我的主页中,我想加载配置数据(地点货币符号),但不显示模型。我在上面链接的教程中使用了类似于登录服务的模式,但是当我尝试在另一个视图(清单)中使用值Provider.of(context).currency时,出现此错误。


  

以下NoSuchMethodError被抛出
  BillListItem(脏,依赖项:[InheritedProvider]):
  getter'currency'在null上被调用。接收方:null尝试调用:
  货币

我不知道与获得Provider.of (上下文).name

的登录名有何不同

这是我的代码:

main.dart

void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MultiProvider(
providers: providers,child: MaterialApp(
title: 'Flutter Demo',theme: ThemeData(
primarySwatch: Colors.blue,),initialRoute: RoutePaths.Login,onGenerateRoute: Router.generateRoute,);
}
}

我要在其中使用提供程序值的视图。

class BillListItem extends StatelessWidget {
final Bill bill;
final Function onTap;
const BillListItem({this.bill,this.onTap});
@override
Widget build(BuildContext context) {
return GestureDetector(
onTap: onTap,child: Container(
margin: EdgeInsets.symmetric(horizontal: 20.0,vertical: 15.0),padding: EdgeInsets.all(10.0),decoration: BoxDecoration(
color: Colors.white,borderRadius: BorderRadius.circular(5.0),boxShadow: [
BoxShadow(
blurRadius: 3.0,offset: Offset(0.0,2.0),color: Color.fromARGB(80,0))
]),child: Column(
crossAxisAlignment: CrossAxisAlignment.start,children: [
Text(bill.billNumber.toString(),style: TextStyle(fontWeight: FontWeight.w900,fontSize: 16.0),Text("${Provider.of(context).currency}${bill.payable.toString()}",],);
}
}

我在其中注入场地的选项卡视图:

class tabcontainer extends StatefulWidget {
@override
State createState() => tabcontainerState();
}
class tabcontainerState extends State {
@override
void initState(){
super.initState();
WidgetsBinding.instance.addPostFrameCallback((_) => _fetchVenue(context));
}
@override
Widget build(BuildContext context) {
return BaseWidget(
model: VenueModel(venueService: Provider.of(context)),builder: (context,model,child) => DefaultTabController(
length: 2,child: Scaffold(
appBar: AppBar(
bottom: TabBar(
isScrollable: false,tabs: [
Tab(icon: Icon(Icons.home)),Tab(icon: Icon(Icons.room_service)),centerTitle : true,title: Text('Exact POS'),actions: [
FutureBuilder(
future: SharedPreferencesHelper.getLanguagecode(),initialData: 'en',builder: (BuildContext context,Asyncsnapshot snapshot) {
return snapshot.hasData
? Buildflag.buildflag(context,snapshot.data)
: Container();
}
),]
),body: SafeArea(
child: TabBarView(
children: [
HomeView(),LoginView(),)
)
);
}
void _fetchVenue(BuildContext context) async {
Api _api = new Api();
VenueService _venueService = new VenueService(api: _api);
VenueModel _venueModel = new VenueModel(venueService: _venueService);
var success = await _venueModel.fetchVenue();
}
}

home_view.dart。我怀疑这可能是我需要注入Venue提供程序的地方,而不是tabcontainer中的地方。

class HomeView extends StatefulWidget{
@override
State createState() => HomeViewState();
}
class HomeViewState extends State {
@override
void initState(){
super.initState();
WidgetsBinding.instance.addPostFrameCallback((_) => showsnackBar());
}
void showsnackBar(){
Scaffold.of(context).showsnackBar(snackBar(
content: Text('Welcome ${Provider.of(context).name}',style: snackBarStyle),backgroundColor: snackBarColor,duration: Duration(seconds: 4),));
}
@override
Widget build(BuildContext context) {
return SafeArea(
child: Scaffold(
backgroundColor: backgroundColor,body: Column(
crossAxisAlignment: CrossAxisAlignment.start,children: [
UIHelper.verticalSpaceSmall,Expanded(
child: Tables(),)
],)
);
}
}

我的视图模型VenueModel

class VenueModel extends BaseModel {
VenueService _venueService;
VenueModel(
{@required VenueService venueService,}
) : _venueService = venueService;
Future fetchVenue() async {
setBusy(true);
var success = await _venueService.fetchVenue();
setBusy(false);
return success;
}
}

我的服务VenueService

class VenueService {
final Api _api;
VenueService({Api api}) : _api = api;
StreamController _venueCOntroller= StreamController();
Stream get venue => _venueController.stream;
Future fetchVenue() async {
var fetchedVenue = await _api.getVenue();
var hasVenue = fetchedVenue != null;
if (hasVenue) {
_venueController.add(fetchedVenue);
}
return hasVenue;
}
}

我的BaseModel.dart

class BaseModel extends ChangeNotifier {
bool _busy = false;
bool get busy => _busy;
void setBusy(bool value) {
_busy = value;
notifyListeners();
}
}

我的提供商设置代码:

List providers = [
...independentServices,...dependentServices,...uiConsumableProviders
];
List independentServices = [
Provider.value(value: Api())
];
List dependentServices = [
ProxyProvider(
builder: (context,api,authenticationService) => AuthenticationService(api: api),ProxyProvider(
builder: (context,venueService) => VenueService(api: api),];
List uiCOnsumableProviders= [
StreamProvider(
builder: (context) => Provider.of(context,listen: false).user,StreamProvider(
builder: (context) => Provider.of(context,listen: false).venue,];

base_widget.dart

class BaseWidget extends StatefulWidget {
final Widget Function(BuildContext context,T model,Widget child) builder;
final T model;
final Widget child;
final Function(T) onmodelReady;
BaseWidget({
Key key,this.builder,this.model,this.child,this.onmodelReady,}) : super(key: key);
_BaseWidgetState createState() => _BaseWidgetState();
}
class _BaseWidgetState extends State> {
T model;
@override
void initState() {
model = widget.model;
if (widget.onmodelReady != null) {
widget.onmodelReady(model);
}
super.initState();
}
@override
Widget build(BuildContext context) {
return ChangeNotifierProvider(
builder: (context) => model,child: Consumer(
builder: widget.builder,child: widget.child,);
}
}




  

以下NoSuchMethodError被抛出
  BillListItem(脏,依赖项:[InheritedProvider]):获取程序
  在null上调用了“ currency”。接收方:null尝试通话:货币

此错误表示Provider.of(context)返回null。这可能是由于两个原因:


  1. null值添加到VenueService中的流中。对于您的代码,情况并非如此,这使我相信这是第二个原因:

  2. VenueService中的流没有发出任何值,因此流的初始数据为null

浏览完代码后,只有在标签视图中才调用fetchVenue中的VenueService

WidgetsBinding.instance.addPostFrameCallback((_) => _fetchVenue(context));

void _fetchVenue(BuildContext context) async {
Api _api = new Api();
VenueService _venueService = new VenueService(api: _api);
VenueModel _venueModel = new VenueModel(venueService: _venueService);
var success = await _venueModel.fetchVenue();
}

在您的_fetchVenue函数中,您实际上是在创建ApiVenueServiceVenueModel的新实例,而这些实例在应用程序的其他任何地方都不会被使用。提供者列表中的实际VenueService保持不变。实际的fetchVenue中的VenueService函数永远不会被调用,这就是Provider.of(context)返回null的原因,因为流没有值。

因此,您可以将_fetchVenue函数替换为此:

void _fetchVenue(BuildContext context) async {
VenueService _venueService = Provider.of(context);
VenueModel _venueModel = new VenueModel(venueService: _venueService);
var success = await _venueModel.fetchVenue();
}

仍然需要进行一些改进,例如_venueModel并未在任何地方使用,但我希望这可以解决您的问题!


推荐阅读
  • 欢乐的票圈重构之旅——RecyclerView的头尾布局增加
    项目重构的Git地址:https:github.comrazerdpFriendCircletreemain-dev项目同步更新的文集:http:www.jianshu.comno ... [详细]
  • 本文讨论了一个关于cuowu类的问题,作者在使用cuowu类时遇到了错误提示和使用AdjustmentListener的问题。文章提供了16个解决方案,并给出了两个可能导致错误的原因。 ... [详细]
  • Java太阳系小游戏分析和源码详解
    本文介绍了一个基于Java的太阳系小游戏的分析和源码详解。通过对面向对象的知识的学习和实践,作者实现了太阳系各行星绕太阳转的效果。文章详细介绍了游戏的设计思路和源码结构,包括工具类、常量、图片加载、面板等。通过这个小游戏的制作,读者可以巩固和应用所学的知识,如类的继承、方法的重载与重写、多态和封装等。 ... [详细]
  • Iamtryingtomakeaclassthatwillreadatextfileofnamesintoanarray,thenreturnthatarra ... [详细]
  • 向QTextEdit拖放文件的方法及实现步骤
    本文介绍了在使用QTextEdit时如何实现拖放文件的功能,包括相关的方法和实现步骤。通过重写dragEnterEvent和dropEvent函数,并结合QMimeData和QUrl等类,可以轻松实现向QTextEdit拖放文件的功能。详细的代码实现和说明可以参考本文提供的示例代码。 ... [详细]
  • android listview OnItemClickListener失效原因
    最近在做listview时发现OnItemClickListener失效的问题,经过查找发现是因为button的原因。不仅listitem中存在button会影响OnItemClickListener事件的失效,还会导致单击后listview每个item的背景改变,使得item中的所有有关焦点的事件都失效。本文给出了一个范例来说明这种情况,并提供了解决方法。 ... [详细]
  • Java容器中的compareto方法排序原理解析
    本文从源码解析Java容器中的compareto方法的排序原理,讲解了在使用数组存储数据时的限制以及存储效率的问题。同时提到了Redis的五大数据结构和list、set等知识点,回忆了作者大学时代的Java学习经历。文章以作者做的思维导图作为目录,展示了整个讲解过程。 ... [详细]
  • JavaSE笔试题-接口、抽象类、多态等问题解答
    本文解答了JavaSE笔试题中关于接口、抽象类、多态等问题。包括Math类的取整数方法、接口是否可继承、抽象类是否可实现接口、抽象类是否可继承具体类、抽象类中是否可以有静态main方法等问题。同时介绍了面向对象的特征,以及Java中实现多态的机制。 ... [详细]
  • 自动轮播,反转播放的ViewPagerAdapter的使用方法和效果展示
    本文介绍了如何使用自动轮播、反转播放的ViewPagerAdapter,并展示了其效果。该ViewPagerAdapter支持无限循环、触摸暂停、切换缩放等功能。同时提供了使用GIF.gif的示例和github地址。通过LoopFragmentPagerAdapter类的getActualCount、getActualItem和getActualPagerTitle方法可以实现自定义的循环效果和标题展示。 ... [详细]
  • 标题: ... [详细]
  • 本文介绍了闭包的定义和运转机制,重点解释了闭包如何能够接触外部函数的作用域中的变量。通过词法作用域的查找规则,闭包可以访问外部函数的作用域。同时还提到了闭包的作用和影响。 ... [详细]
  • 在Android开发中,使用Picasso库可以实现对网络图片的等比例缩放。本文介绍了使用Picasso库进行图片缩放的方法,并提供了具体的代码实现。通过获取图片的宽高,计算目标宽度和高度,并创建新图实现等比例缩放。 ... [详细]
  • Spring源码解密之默认标签的解析方式分析
    本文分析了Spring源码解密中默认标签的解析方式。通过对命名空间的判断,区分默认命名空间和自定义命名空间,并采用不同的解析方式。其中,bean标签的解析最为复杂和重要。 ... [详细]
  • CSS3选择器的使用方法详解,提高Web开发效率和精准度
    本文详细介绍了CSS3新增的选择器方法,包括属性选择器的使用。通过CSS3选择器,可以提高Web开发的效率和精准度,使得查找元素更加方便和快捷。同时,本文还对属性选择器的各种用法进行了详细解释,并给出了相应的代码示例。通过学习本文,读者可以更好地掌握CSS3选择器的使用方法,提升自己的Web开发能力。 ... [详细]
  • 本文介绍了南邮ctf-web的writeup,包括签到题和md5 collision。在CTF比赛和渗透测试中,可以通过查看源代码、代码注释、页面隐藏元素、超链接和HTTP响应头部来寻找flag或提示信息。利用PHP弱类型,可以发现md5('QNKCDZO')='0e830400451993494058024219903391'和md5('240610708')='0e462097431906509019562988736854'。 ... [详细]
author-avatar
萧勇志762852
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有