颤动如何让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' 的实例,而不是通过参数传入它的 null 谢谢你我不再出错了,很高兴知道我需要未来的建设者将未来传递给正常的方法。但我遇到了问题,方法 classList 不会显示任何内容,只是进行内部调用 txt.do/1dsp6

以上是关于颤动如何让gridview显示像按钮这样的firebase数据的主要内容,如果未能解决你的问题,请参考以下文章

如何阻止 Gridview.builder 的滚动条在颤动中显示

颤动-在gridview上换行时如何设置宽度?

如何在颤动中计算 GridView.builder 的 childAspectRatio

颤动:GridView 未正确显示

如何在颤动中直接将数据从 StreamBuilder 获取到 GridView 中?

如何使用clipPath在颤动中绘制这个按钮?