颤抖如何使gridview像按钮一样显示firebase数据 [英] flutter how to make gridview show firebase data like buttons

查看:88
本文介绍了颤抖如何使gridview像按钮一样显示firebase数据的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试让Streambuilder显示gridview,但是它返回此错误,我正在将方法classList()调用到脚手架主体中的容器中

I am trying to user Streambuilder to display gridview, but it return this error, I am calling the method classList() to container in scaffold body

database = FirebaseDatabase.instance

database = FirebaseDatabase.instance

我想显示classData,显示0,1,2..etc.我想在RaidView中显示(每个孩子一个按钮中的"className","classSection")为RaisedButtons

I want to show classData, show 0,1,2..etc I want to show ('className','classSection' in one button per child) in gridview as RaisedButtons

执行以下代码时,我会收到此错误

I get this error when the code below is executed

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();
          }
        });
  }

整个dart文件

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');
    }
  }
}

推荐答案

主要问题是当我们在firebase的".child()"方法中传递空字符串或空字符串时,它将给我们split("/")错误,因为在内部它将尝试从字符串中拆分并尝试获取数据 从它.

Main problem is when we pass blank or null string in ".child()" method of firebase, it will give us split("/") error because internally it will try to split from string and get try to get data from it.

现在,您代码中的问题是,在使用StreamBuilder()从Firebase用户ID生成数据之前,您要在小部件重写方法中调用"classList(userUid)",但userUid为空,正如我上面所说, 如果在该".child()"方法中传递空白或null,firebase将给我们提供split("/")错误.

Now the problem in your code is you are calling "classList(userUid)" in the widget override method before the data come from firebase userid with use of StreamBuilder() but the userUid is blank and as i said above, firebase will give us split("/") error if we pass blank or null in that ".child()" method.

因此,结论是我们必须等待firebase userid直到从异步结果中获取它,因为要获取firebase userid这是异步任务,我们必须等待,直到结果带有await关键字.

So the conclusion is we have to wait for firebase userid until we get it from async result because to get firebase userid which is async task and we have to wait for that until result come with using await keyword.

所以这是答案,如何做到这一点: 您必须使用以下的Future<>来替换小部件中的身体部分:

So Here is the answer, how to do that: You have to replace your body portion in widget with the use of future<> such as below:

@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()"方法中使用.

Also the best practice is that you have to get firebase userid only in "initState()" method which will call only once during lifecycle. so declare "FirebaseUser user" globally in your class and then call your "userUi()" in only "initState()" method.

这篇关于颤抖如何使gridview像按钮一样显示firebase数据的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆