颤动如何让gridview显示像按钮这样的firebase数据
Posted
技术标签:
【中文标题】颤动如何让gridview显示像按钮这样的firebase数据【英文标题】:flutter how to make gridview show firebase data like buttons 【发布时间】:2019-09-10 12:44:13 【问题描述】:我正在尝试使用 Streambuilder 来显示 gridview,但它返回此错误,我正在调用方法 classList() 到脚手架主体中的容器
数据库 = FirebaseDatabase.instance
我想显示 classData,显示 0,1,2..etc 我想在 gridview 中显示('className','classSection' in one button per child)作为 RaisedButtons
执行以下代码时出现此错误
I/flutter ( 5433): ══╡ EXCEPTION CAUGHT BY WIDGETS LIBRARY ╞═══════════════════════════════════════════════════════════
I/flutter ( 5433): The following NoSuchMethodError was thrown building HomePage(dirty, state: _HomePage#055be):
I/flutter ( 5433): The method 'split' was called on null.
I/flutter ( 5433): Receiver: null
I/flutter ( 5433): Tried calling: split("/")
I/flutter ( 5433):
I/flutter ( 5433): When the exception was thrown, this was the stack:
I/flutter ( 5433): #0 Object.noSuchMethod (dart:core/runtime/libobject_patch.dart:50:5)
I/flutter ( 5433): #1 DatabaseReference.child (file:///G:/flutter/.pub-cache/hosted/pub.dartlang.org/firebase_database-2.0.3/lib/src/database_reference.dart:24:58)
I/flutter ( 5433): #2 _HomePage.classList (package:barcode_scan_example/home_page.dart:169:44)
I/flutter ( 5433): #3 _HomePage.build (package:barcode_scan_example/home_page.dart:265:30)
I/flutter ( 5433): #4 StatefulElement.build (package:flutter/src/widgets/framework.dart:3825:27)
I/flutter ( 5433): #5 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:3736:15)
I/flutter ( 5433): #6 Element.rebuild (package:flutter/src/widgets/framework.dart:3559:5)
I/flutter ( 5433): #7 ComponentElement._firstBuild (package:flutter/src/widgets/framework.dart:3716:5)
I/flutter ( 5433): #8 StatefulElement._firstBuild (package:flutter/src/widgets/framework.dart:3864:11)
I/flutter ( 5433): #9 ComponentElement.mount (package:flutter/src/widgets/framework.dart:3711:5)
I/flutter ( 5433): #10 Element.inflateWidget (package:flutter/src/widgets/framework.dart:2956:14)
I/flutter ( 5433): #11 Element.updateChild (package:flutter/src/widgets/framework.dart:2759:12)
I/flutter ( 5433): #12 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:3747:16)
I/flutter ( 5433): #13 Element.rebuild (package:flutter/src/widgets/framework.dart:3559:5)
I/flutter ( 5433): #14 BuildOwner.buildScope (package:flutter/src/widgets/framework.dart:2273:33)
I/flutter ( 5433): #15 _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding&PaintingBinding&SemanticsBinding&RendererBinding&WidgetsBinding.drawFrame (package:flutter/src/widgets/binding.dart:700:20)
I/flutter ( 5433): #16 _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding&PaintingBinding&SemanticsBinding&RendererBinding._handlePersistentFrameCallback (package:flutter/src/rendering/binding.dart:268:5)
I/flutter ( 5433): #17 _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding._invokeFrameCallback (package:flutter/src/scheduler/binding.dart:988:15)
I/flutter ( 5433): #18 _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding.handleDrawFrame (package:flutter/src/scheduler/binding.dart:928:9)
I/flutter ( 5433): #19 _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding._handleDrawFrame (package:flutter/src/scheduler/binding.dart:840:5)
I/flutter ( 5433): #23 _invoke (dart:ui/hooks.dart:209:10)
I/flutter ( 5433): #24 _drawFrame (dart:ui/hooks.dart:168:3)
I/flutter ( 5433): (elided 3 frames from package dart:async)
classList()
StreamBuilder(
stream:
database.reference().child('user').child(userUid).child('classData').orderByKey().onValue,
builder: (BuildContext context, AsyncSnapshot<Event> snapshot)
if (snapshot.hasData)
if (snapshot.data.snapshot.value != null)
Map<dynamic, dynamic> map = snapshot.data.snapshot.value;
List<dynamic> list = map.values.toList();
print("list is : $list");
return GridView.builder(
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 3),
itemCount: list.length,
padding: EdgeInsets.all(2.0),
itemBuilder: (BuildContext context, int index)
print("print job $list[index]["className"]");
return Container(
child: RaisedButton(
onPressed: null,
child: Text(
"$list[index]["className"]\n $list[index]["classSection"]"),
),
padding: EdgeInsets.all(2.0),
);
,
);
else
return Container(
child: Center(
child: Text(
"There's no Class registered in the system",
style: TextStyle(fontSize: 20.0, color: Colors.grey),
textAlign: TextAlign.center,
)));
else
return CircularProgressIndicator();
);
整个飞镖文件
import 'package:flutter/material.dart';
import 'auth.dart';
import 'auth_provider.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/services.dart';
import 'make_class.dart';
import 'dart:async';
import 'package:barcode_scan/barcode_scan.dart';
import 'package:firebase_database/firebase_database.dart';
import 'qr_screen.dart';
class HomePage extends StatefulWidget
@override
_HomePage createState() => _HomePage();
enum ScaffoldType student, lecturer
ScaffoldType _scaffoldType = ScaffoldType.lecturer;
class _HomePage extends State<HomePage>
final FirebaseDatabase database = FirebaseDatabase.instance;
String barcode = "";
String userUid;
var userClass;
Future<void> _signOut(BuildContext context) async
try
final BaseAuth auth = AuthProvider.of(context).auth;
await auth.signOut();
catch (e)
print(e);
@override
void initState()
super.initState();
userUi();
setState(() async*
FirebaseDatabase database;
database = FirebaseDatabase.instance;
database.setPersistenceEnabled(true);
database.setPersistenceCacheSizeBytes(10000000);
);
Future reUser() async
FirebaseUser user = await FirebaseAuth.instance.currentUser();
print(user.uid);
var userUid = user.uid;
var userWho = await database
.reference()
.child('user')
.child(userUid)
.once()
.then((DataSnapshot snapshot)
Map<dynamic, dynamic> data = snapshot.value;
var isL = data.values.toList();
print(isL[1]);
print(data.values);
if (isL[1].toString().toLowerCase() == "true")
_scaffoldType = ScaffoldType.lecturer;
print('lecturer');
else if (isL[1].toString().toLowerCase() == "false")
_scaffoldType = ScaffoldType.student;
print("student");
);
// print(userWho);
userUi() async
FirebaseUser user = await FirebaseAuth.instance.currentUser();
print(user.uid);
return user.uid;
classList(userUid)
print(userUid);
StreamBuilder(
stream:
database.reference().child('user').child(userUid).child('classData').orderByKey().onValue,
builder: (BuildContext context, AsyncSnapshot<Event> snapshot)
if (snapshot.hasData)
if (snapshot.data.snapshot.value != null)
Map<dynamic, dynamic> map = snapshot.data.snapshot.value;
List<dynamic> list = map.values.toList();
print("list is : $list");
return GridView.builder(
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 3),
itemCount: list.length,
padding: EdgeInsets.all(2.0),
itemBuilder: (BuildContext context, int index)
print("print job $list[index]["className"]");
return Container(
child: RaisedButton(
onPressed: (),
child: Text(
"$list[index]["className"]\n $list[index]["classSection"]"),
),
padding: EdgeInsets.all(2.0),
);
,
);
else
return Container(
child: Center(
child: Text(
"There's no Class registered in the system",
style: TextStyle(fontSize: 20.0, color: Colors.grey),
textAlign: TextAlign.center,
)));
else
return CircularProgressIndicator();
);
@override
Widget build(BuildContext context)
// var userUid = userUi();
reUser();
return Scaffold(
appBar: AppBar(
title: Text('Welcome'),
actions: <Widget>[
FlatButton(
child: Icon(Icons.exit_to_app),
onPressed: () => _signOut(context),
)
],
),
bottomNavigationBar: BottomAppBar(
notchMargin: 8.0,
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Padding(
padding: const EdgeInsets.fromLTRB(35, 0, 35, 0),
child: Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Column(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.center,
children: buttonBelow(),
),
Column(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.center,
children: buttonBelow2(),
),
],
),
),
),
shape: CircularNotchedRectangle(),
),
resizeToAvoidBottomInset: true,
floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked,
floatingActionButton: Container(
height: 80,
width: 80,
child: FittedBox(
child: FloatingActionButton(
onPressed: scan,
child: Icon(
Icons.camera,
size: 35,
),
elevation: 2.0,
),
),
),
body: Container(child: classList(userUi()),),
);
List<Widget> buttonBelow()
if (_scaffoldType == ScaffoldType.lecturer)
return <Widget>[
FlatButton(
child: Icon(
Icons.add_circle,
semanticLabel: "Add Class",
size: 45,
),
onPressed: ()
Navigator.push(
context,
MaterialPageRoute(builder: (context) => MakeClass()),
);
,
shape:
RoundedRectangleBorder(borderRadius: BorderRadius.circular(180)),
),
Text("Add Class")
];
else
return <Widget>[
Opacity(
opacity: 0,
child: FlatButton(
onPressed: () ,
child: Icon(
Icons.add_circle,
semanticLabel: "Add Class",
size: 45,
),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(180)),
),
),
Opacity(opacity: 0, child: Text("Add Class"))
];
List<Widget> buttonBelow2()
if (_scaffoldType == ScaffoldType.lecturer)
return <Widget>[
FlatButton(
child: Icon(
Icons.blur_on,
semanticLabel: "QRCode",
size: 45,
),
onPressed: ()
Navigator.push(
context,
MaterialPageRoute(builder: (context) => QrScreen()),
);
,
shape:
RoundedRectangleBorder(borderRadius: BorderRadius.circular(180)),
),
Text("QRCode")
];
Future scan() async
try
String barcode = await BarcodeScanner.scan();
setState(() => this.barcode = barcode);
on PlatformException catch (e)
if (e.code == BarcodeScanner.CameraAccessDenied)
setState(()
this.barcode = 'The user did not grant the camera permission!';
);
else
setState(() => this.barcode = 'Unknown error: $e');
on FormatException
setState(() => this.barcode =
'null (User returned using the "back"-button before scanning anything. Result)');
catch (e)
setState(() => this.barcode = 'Unknown error: $e');
【问题讨论】:
【参考方案1】:The method 'split' was called on null.
每当您引用不存在的路径时,就会发生这种类型的异常。因此,请确保您的 firebase 数据库的路径正确。
【讨论】:
【参考方案2】:主要问题是当我们在firebase的“.child()”方法中传递空白或空字符串时,它会给我们split(“/”)错误,因为在内部它会尝试从字符串中拆分并尝试获取数据 来自它。
现在代码中的问题是,在数据来自 firebase userid 并使用 StreamBuilder() 之前,您在小部件覆盖方法中调用“classList(userUid)”,但 userUid 为空白,正如我上面所说, 如果我们在那个 ".child()" 方法中传递空白或 null,firebase 会给我们 split("/") 错误。
所以结论是我们必须等待 firebase userid 直到我们从异步结果中获取它,因为要获取 firebase userid 这是异步任务,我们必须等待直到结果使用 await 关键字。
所以这是答案,如何做到这一点: 您必须使用 future 替换小部件中的身体部分,如下所示:
@override
Widget build(BuildContext context)
return Scaffold(
appBar: AppBar(
title: Text('Welcome'),
actions: <Widget>[
FlatButton(
child: Icon(Icons.exit_to_app),
onPressed: () => _signOut(context),
)
],
),
bottomNavigationBar: BottomAppBar(
notchMargin: 8.0,
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Padding(
padding: const EdgeInsets.fromLTRB(35, 0, 35, 0),
child: Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Column(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.center,
children: buttonBelow(),
),
Column(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.center,
children: buttonBelow2(),
),
],
),
),
),
shape: CircularNotchedRectangle(),
),
resizeToAvoidBottomInset: true,
floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked,
floatingActionButton: Container(
height: 80,
width: 80,
child: FittedBox(
child: FloatingActionButton(
onPressed: scan,
child: Icon(
Icons.camera,
size: 35,
),
elevation: 2.0,
),
),
),
body: new FutureBuilder<FirebaseUser>(
future: FirebaseAuth.instance.currentUser(),
builder: (BuildContext context, AsyncSnapshot<FirebaseUser> snapshot)
if (snapshot.connectionState == ConnectionState.done)
return new Container(child: classList(snapshot.data.uid));
else
return new Text('Loading...');
,
),
);
此外,最佳做法是您必须仅在“initState()”方法中获取 firebase 用户 ID,该方法在生命周期中仅调用一次。所以在你的类中全局声明“FirebaseUser用户”,然后调用你的“userUi()” 仅在“initState()”方法中。
【讨论】:
它没有用,在挖掘之后似乎 userUid 没有通过,因为它是从异步方法生成的,并且流生成器不是异步的,当我制作 streambuild 异步方法时它不起作用 请发布您的整个班级以检查从哪里分配 userUid 以及从哪里使用 streambuilder 调用 classList() 方法 我添加了整个 dart 文件,这是我写的第二个完整代码,我写的第一个是命令 shell java 2 年前:D 所以不要介意其中的疯狂嘘!抱歉,*** 没有刷新就不会更新收件箱,所以我有一段时间没有注意到。 我忘了说我得到它说 'Future以上是关于颤动如何让gridview显示像按钮这样的firebase数据的主要内容,如果未能解决你的问题,请参考以下文章
如何阻止 Gridview.builder 的滚动条在颤动中显示
如何在颤动中计算 GridView.builder 的 childAspectRatio