- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我使用 Flutter 构建了一个网络应用程序。几个月前构建和部署没有任何问题。今天没有更新任何代码就跳回到代码中,现在出现以下错误:
Error:Expected a value of type 'List<String>', but got one of type 'List<dynamic>'
══╡ EXCEPTION CAUGHT BY WIDGETS LIBRARY ╞═══════════════════════════════════════════════════════════
The following JSNoSuchMethodError was thrown building NewHomeScreen(dirty, dependencies:
[_EffectiveTickerMode, _InheritedProviderScope<List<ContentModel>>, MediaQuery], state:
_NewHomeScreenState#295f1(tickers: tracking 2 tickers)):
NoSuchMethodError: invalid member on null: 'length'
这是我从 Firebase 获取数据的位置和方式:
void main() => runApp(MyApp());
class MyApp extends StatefulWidget {
// This widget is the root of your application.
@override
_MyAppState createState() => _MyAppState();
}
@override
void initState() {}
class _MyAppState extends State<MyApp> {
@override
Widget build(BuildContext context) {
final linksCollection = Firestore.instance.collection('links');
final contentCollection = Firestore.instance.collection('content');
final contentObjects = contentCollection.snapshots().map((snapshot) {
return snapshot.documents
.map((doc) => ContentModel.fromDocument(doc))
.toList();
});
return MultiProvider(
providers: [
StreamProvider<List<ContentModel>>(
create: (_) => contentObjects,
initialData: [],
catchError: (BuildContext context, e) {
print("Error:$e");
return null;
},
),
Provider<CollectionReference>(create: (_) => linksCollection),
],
child: MaterialApp(
title: 'My App',
debugShowCheckedModeBanner: false,
theme: ThemeData(primarySwatch: Colors.blue, fontFamily: 'IBM_Plex'),
initialRoute: '/',
routes: {'/': (context) => NewHomeScreen()},
),
);
}
}
然后我通过像这样使用 Provider 访问它来在整个应用程序中使用这些数据:
class NewHomeScreen extends StatefulWidget {
@override
_NewHomeScreenState createState() => _NewHomeScreenState();
}
class _NewHomeScreenState extends State<NewHomeScreen>
with TickerProviderStateMixin {
@override
void initState() {
super.initState();
}
@override
Widget build(BuildContext context) {
final contentObjects = Provider.of<List<ContentModel>>(context);
List<ContentModel> expertList = [];
for (var data in contentObjects) {
if(data.topic == 'expert') {
expertList.add(data);
}
}
return Scaffold(
body: CustomScrollView(
slivers: <Widget>[
SliverAppBar(
leading: Container(
child: Padding(
padding: EdgeInsets.only(left: 10.0),
child: GestureDetector(
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => NewHomeScreen(),
),
);
},
),
)
),
backgroundColor: appBarColor,
expandedHeight: 50.0,
pinned: true,
flexibleSpace: FlexibleSpaceBar(
title: Align(
alignment: Alignment.center,
),
centerTitle: true,
stretchModes: [
StretchMode.blurBackground,
StretchMode.zoomBackground
],
background: Image.network(
'https://www.image.com',
fit: BoxFit.cover,
),
),
actions: <Widget>[
InkResponse(
onTap: () {
Navigator.push(
context,
SlideRightRoute(
page: SearchScreen(),
),
);
},
child: new Padding(
padding: const EdgeInsets.all(12.0),
child: Icon(
Icons.search,
size: 26.0,
color: Colors.white,
),
),
),
],
),
SliverToBoxAdapter(
child: Column(
children: <Widget>[
FadeIn(1.00, Center(child: HeaderWidget())),
FadeIn(2.33, Center(child: HashtagRow())),
SizedBox(
height: 20,
),
SizedBox(height: 50),
FadeIn(
2.66,
SectionContainer(
sectionTitle: "Expertise in focus",
child: Padding(
padding: EdgeInsets.only(top: 13, bottom: 13),
child: Container(
height: 450,
child: ListView.builder(
padding: EdgeInsets.only(left: 50, right: 50),
scrollDirection: Axis.horizontal,
itemCount: expertList.length,
itemBuilder: (ctx, index) {
return GestureDetector(
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => ExpertDetailsScreen(
contentModel: expertList[index],
),
),
);
},
child: Column(
children: <Widget>[
Padding(
padding: EdgeInsets.only(
left: 15.0,
right: 15.0,
),
child: Hero(
tag: expertList[index].title.toString(),
child: Align(
alignment: Alignment.centerLeft,
child: CircleAvatar(
radius: 150.0,
backgroundImage: NetworkImage(
expertList[index].imglink),
backgroundColor: Colors.transparent,
),
),
),
),
Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(8.0),
),
child: Padding(
padding: const EdgeInsets.all(10),
child: Center(
child: Text(
expertList[index].tags[1],
textAlign: TextAlign.center,
style: forumNameTextStyleTwo,
),
),
),
),
SizedBox(height: 3),
Text(
expertList[index].title,
textAlign: TextAlign.center,
style: labelTextStyle,
),
],
),
);
},
),
),
),
),
),
SizedBox(height: 50)
],
),
)
],
),
floatingActionButton: FloatingActionButton.extended(
onPressed: () {
Navigator.push(
context,
ScaleRoute(
page: AddResource(),
),
);
},
label: Text('Suggest a resource'),
icon: Icon(Icons.add),
backgroundColor: myColor,
),
);
}
void htmlOpenLink(String s) {
html.window.open(s, '_blank');
}
}
class SlideRightRoute extends PageRouteBuilder {
final Widget page;
SlideRightRoute({this.page})
: super(
pageBuilder: (
BuildContext context,
Animation<double> animation,
Animation<double> secondaryAnimation,
) =>
page,
transitionsBuilder: (
BuildContext context,
Animation<double> animation,
Animation<double> secondaryAnimation,
Widget child,
) =>
SlideTransition(
position: Tween<Offset>(
begin: const Offset(-1, 0),
end: Offset.zero,
).animate(
CurvedAnimation(
parent: animation,
curve: Curves.fastOutSlowIn,
),
),
child: child,
),
);
}
class ScaleRoute extends PageRouteBuilder {
final Widget page;
ScaleRoute({this.page})
: super(
pageBuilder: (
BuildContext context,
Animation<double> animation,
Animation<double> secondaryAnimation,
) =>
page,
transitionsBuilder: (
BuildContext context,
Animation<double> animation,
Animation<double> secondaryAnimation,
Widget child,
) =>
ScaleTransition(
scale: Tween<double>(
begin: 0.0,
end: 1.0,
).animate(
CurvedAnimation(
parent: animation,
curve: Curves.fastOutSlowIn,
),
),
child: child,
),
);
}
class MyCustomClipper extends CustomClipper<Path> {
final double distanceFromWall = 12;
final double controlPointDistanceFromWall = 2;
@override
Path getClip(Size size) {
final double height = size.height;
final double halfHeight = size.height * 0.5;
final double width = size.width;
Path clippedPath = Path();
clippedPath.moveTo(0, halfHeight);
clippedPath.lineTo(0, height - distanceFromWall);
clippedPath.quadraticBezierTo(0 + controlPointDistanceFromWall,
height - controlPointDistanceFromWall, 0 + distanceFromWall, height);
clippedPath.lineTo(width, height);
clippedPath.lineTo(width, 0 + 30.0);
clippedPath.quadraticBezierTo(width - 5, 0 + 5.0, width - 35, 0 + 15.0);
clippedPath.close();
return clippedPath;
}
@override
bool shouldReclip(CustomClipper<Path> oldClipper) {
return true;
}
}
class CustomShapeBorder extends ShapeBorder {
final double distanceFromWall = 12;
final double controlPointDistanceFromWall = 2;
@override
EdgeInsetsGeometry get dimensions => null;
@override
Path getInnerPath(Rect rect, {TextDirection textDirection}) {
return null;
}
@override
Path getOuterPath(Rect rect, {TextDirection textDirection}) {
return getClip(Size(220.0, 70.0));
}
@override
void paint(Canvas canvas, Rect rect, {TextDirection textDirection}) {}
@override
ShapeBorder scale(double t) {
return null;
}
Path getClip(Size size) {
Path clippedPath = Path();
clippedPath.moveTo(0 + distanceFromWall, 0);
clippedPath.quadraticBezierTo(0 + controlPointDistanceFromWall,
0 + controlPointDistanceFromWall, 0, 0 + distanceFromWall);
clippedPath.lineTo(0, size.height - distanceFromWall);
clippedPath.quadraticBezierTo(
0 + controlPointDistanceFromWall,
size.height - controlPointDistanceFromWall,
0 + distanceFromWall,
size.height);
clippedPath.lineTo(size.width - distanceFromWall, size.height);
clippedPath.quadraticBezierTo(
size.width - controlPointDistanceFromWall,
size.height - controlPointDistanceFromWall,
size.width,
size.height - distanceFromWall);
clippedPath.lineTo(size.width, size.height * 0.6);
clippedPath.quadraticBezierTo(
size.width - 1,
size.height * 0.6 - distanceFromWall,
size.width - distanceFromWall,
size.height * 0.6 - distanceFromWall - 3);
clippedPath.lineTo(0 + distanceFromWall + 6, 0);
clippedPath.close();
return clippedPath;
}
}
这是数据的模型类:
class ContentModel {
String title;
String description;
String imglink;
int contentId;
List<String> tags;
List<String> focusAreas;
int likeCount;
String myIcon;
bool isNew;
String content;
String contentLink;
String appColor;
double positionVar;
String detailScreenLink;
String documentId;
String topic;
String hashtag;
ContentModel(
{this.title,
this.description,
this.imglink,
this.contentId,
this.tags,
this.likeCount,
this.myIcon,
this.isNew,
this.content,
this.contentLink,
this.appColor,
this.positionVar,
this.detailScreenLink,
this.documentId,
this.topic,
this.focusAreas,
this.hashtag});
Map<String, dynamic> toMap() {
return {
'title': title,
'description': description,
'imglink': imglink,
'contentId': contentId,
'tags': tags,
'likeCount': likeCount,
'isNew': isNew,
'content': content,
'contentLink': contentLink,
'appColor': appColor,
'positionVar': positionVar,
'detailScreenLink': detailScreenLink,
'documentId': documentId,
'topic': topic,
'focusAreas': focusAreas,
'hashtag': hashtag
};
}
static ContentModel fromDocument(DocumentSnapshot document) {
if (document == null || document.data == null) return null;
return ContentModel(
documentId: document.documentID,
imglink: document.data['imglink'],
title: document.data['title'],
description: document.data['description'],
likeCount: document.data['likeCount'],
tags: document.data['tags'],
isNew: document.data['isNew'],
content: document.data['content'],
contentLink: document.data['contentLink'],
appColor: document.data['appColor'],
positionVar: document.data['positionVar'],
detailScreenLink: document.data['detailScreenLink'],
topic: document.data['topic'],
focusAreas: document.data['focusAreas'],
hashtag: document.data['hashtag']);
}
Map toJson() => {
'title': title,
'description': description,
'imglink': imglink,
'contentId': contentId,
'tags': tags,
'likeCount': likeCount,
'isNew': isNew,
'content': content,
'contentLink': contentLink,
'appColor': appColor,
'positionVar': positionVar,
'detailScreenLink': detailScreenLink,
'documentId': documentId,
'topic': topic,
'focusAreas': focusAreas,
'hashtag': hashtag
};
}
最佳答案
给定
List<dynamic> dynamicList;
你可以使用
var stringList = List<String>.from(dlist);
转换 List<dynamic>
至 List<String>
因此你需要修复你的模式:
static ContentModel fromDocument(DocumentSnapshot document) {
if (document == null || document.data == null) return null;
return ContentModel(
documentId: document.documentID,
imglink: document.data['imglink'],
title: document.data['title'],
description: document.data['description'],
likeCount: document.data['likeCount'],
tags: List<String>.from(document.data['tags']),// to convert a List<dynamic> to List<String>
isNew: document.data['isNew'],
content: document.data['content'],
contentLink: document.data['contentLink'],
appColor: document.data['appColor'],
positionVar: document.data['positionVar'],
detailScreenLink: document.data['detailScreenLink'],
topic: document.data['topic'],
focusAreas: List<String>.from(document.data['focusAreas']), //to convert a List<dynamic> to List<String>
hashtag: document.data['hashtag']);}
关于firebase - 使用 Provider 的 Flutter Web 和 Firebase List<String> 和 List <dynamic> 错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62888290/
我正在尝试从flutter应用程序构建apk,但出现此错误: Note: /mnt/Software/Linux/Flutter/flutter/.pub-cache/hosted/pub.dartl
我有一个名为 X 的较大应用程序,还有另一个名为 Y 的较小应用程序。他们现在彼此分开,并且工作正常。我想将应用程序 Y 集成到 X 中。我想将 Y 的代码放入 X 项目中,但它们应该有不同的 Mai
在android Studio中选择Create New Flutter Project,出现如下4个选项。 Flutter 应用程序 Flutter 插件 Flutter 包 flutter 模块
我看到我的 flutter 项目生成了一个文件 ios/Flutter/Flutter.podspec ,这个文件有什么用? 如果它与生成的 Flutter.framework 有关? 我应该将它包含
我尝试过的 在包含flutter SDK的位置添加/编辑.bash_profile.rtf文件。 导出PATH = / Users / temur / Documents / Projects / F
Flutter 日志会打印数千个详细/垃圾邮件日志。 我正在尝试调试一个复杂的应用程序,但是打印太冗长了,以至于我很难找到我自己打印的东西。 有没有办法禁用详细? 就像是: Logger.level.
在flutter 1.22更新之后,我在Lineargradient colors属性中遇到错误,这给我一个错误,即未定义名称colors参数。.在Android中更新flutter和flutter插
在下面的代码 widget.hintText 中给出错误,我试图将日期选择器作为单独的组件,并在从其他文件调用它时动态传递提示文本值。 import 'package:date_field/date_
在下面的代码 widget.hintText 中给出错误,我试图将日期选择器作为单独的组件,并在从其他文件调用它时动态传递提示文本值。 import 'package:date_field/date_
Flutter 1.0 发布后,我正在按照步骤搭建 Flutter 开发环境。 在步骤中(如所附屏幕截图所示),它说要更新 $PATH 两次,一次使用 flutter 工具的路径 export PAT
我有一个用 flutter 编写的移动应用程序,我想将其转换为 flutter_web 应用程序(集成 flutter_web 尚不可用)。我目前遇到包裹问题。 我已按照本网站中列出的说明进行操作 h
如何向我的 Flutter 路由添加自定义转换?这是我目前的路线结构。 class MyApp extends StatelessWidget { // This widget is the
我正在尝试通过 URL 在 webview 中显示网页。我试过 flutter_webview_plugin 插件,但是当我在浏览器上运行项目时它不起作用。 在 flutter web applica
我正在使用 animatedContainer 在按下按钮时显示 listView.builder()。这是一个要显示的简单子(monad)列表,但问题是我不知道 ListView 构建器的高度会传递
我目前正在我的应用程序中制作渐变背景动画......我正在使用 lottie 动画的帮助下这样做!我试图将它封装在一个容器中并成功地做到了。但是有一个问题,尽管我将高度更改为大于 2000 的东西,但
美好的一天! 我无法弄清楚如何使用 google 标签管理器设置 flutter。我找到了 this package包括标签管理器 api。但是我不知道如何正确配置它。 (在网络上我只需要复制粘贴一个
我的购物车模型如下 class Cart { String description; double unitCost; double amount; int quantity; S
在 Flutter 应用程序中,我想为在线托管的资源(图像、视频等)实现缓存。 我希望它能在原生平台 (Android/iOS)(例如使用文件系统)和网络(例如使用 IndexedDB)上运行。 Fl
我写了一个页面,在顶部一切都很好,应该是这样。在底部我有一个事件的历史。我的容器的宽度是自动确定的(取决于屏幕的宽度),而高度 - 不,在不同的设备上有不同的高度(底部的缩进是不同的)。是否可以自动确
我正在处理一个页面,其中有一些字段,例如 textfield 和 slider。在页面的末尾必须有一个用于进行下一步的按钮,该按钮被包裹在 Align 中以在页面之间具有固定位置。 另一方面,resi
我是一名优秀的程序员,十分优秀!