флаттер, как заставить gridview отображать данные базы данных, такие как кнопки - PullRequest
1 голос
/ 20 апреля 2019

Я пытаюсь использовать Streambuilder для отображения gridview, но он возвращает эту ошибку, я вызываю метод classList () для контейнера в теле scaffold

база данных = FirebaseDatabase.instance

Database Image

Я хочу показать classData, показать 0,1,2..etc Я хочу показать ('className', 'classSection' в одной кнопке для каждого ребенка) в gridview как 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 Ответ

0 голосов
/ 20 апреля 2019

Основная проблема в том, что когда мы передаем пустую или пустую строку в методе .child () firebase, это даст нам ошибку split ("/"), потому что внутри он попытается отделить строку и попытаться получить данные.из него.

Теперь проблема в вашем коде заключается в том, что вы вызываете "classList (userUid)" в методе переопределения виджета до того, как данные поступают из идентификатора пользователя firebase с использованием StreamBuilder (), но userUid пуст и каккак я сказал выше, firebase выдаст нам ошибку split ("/"), если мы передадим пустое или нулевое значение в этом методе ".child ()".

Таким образом, вывод заключается в том, что мы должны ждать идентификатор пользователя firebase, пока мыполучить его из асинхронного результата, потому что для получения идентификатора пользователя Firebase, который является асинхронной задачей, мы должны ждать этого, пока результат не будет получен с использованием ключевого слова await.

Итак, вот ответ, как это сделать: Вызаменить часть вашего тела в виджете на использование будущего <>, как показано ниже:

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

Также рекомендуется, чтобы вы использовали идентификатор пользователя только в "initS"tate () "метод, который будет вызываться только один раз в течение жизненного цикла.поэтому объявите «FirebaseUser user» глобально в своем классе, а затем вызовите свой «userUi ()» только в методе initState ().

...