Проблема с асинхронным кодом во флаттере, нужно, чтобы мой код запускался построчно - PullRequest
0 голосов
/ 18 июня 2020

Я впервые пытаюсь создать приложение для флаттера, и у меня много проблем с этим. У меня проблема, особенно с асинхронным кодированием. У меня есть постоянная нижняя панель навигации для домашней страницы. Что я хочу от кнопки Form nab, так это проверить, заполнил ли уже вошедший пользователь форму или нет. Если пользователь не заполнил форму, я хочу показать DonorFormHomeBefore (), и если пользователь уже заполнил форму, то при нажатии на форму из панели навигации я хочу показать DonorFormHomeAfter (). Чтобы реализовать это, я использовал оболочку и попытался получить экземпляр базы данных из firebase. Но вместо получения данных из firebase код запускает более позднюю часть кодов и вызывает ошибку. , он переходит к более поздней части кода и получает сообщение об ошибке:

Exception caught by widgets library ═══════════════════════════════════
The following NoSuchMethodError was thrown building DonorFormWrapper(dirty, dependencies: [_InheritedProviderScope<DonorUser>], state: _DonorFormWrapperState#a1b86):
Class 'Future<dynamic>' has no instance method '[]'.
Receiver: Instance of 'Future<dynamic>'
Tried calling: []("name")

The relevant error-causing widget was
    DonorFormWrapper 
lib\…\Home\donor_home.dart:21
When the exception was thrown, this was the stack
#0      Object.noSuchMethod  (dart:core-patch/object_patch.dart:53:5)
#1      _DonorFormWrapperState.build 
package:PlasmaBank/…/Home/donor_form_wrapper.dart:33
#2      StatefulElement.build 
package:flutter/…/widgets/framework.dart:4619
#3      ComponentElement.performRebuild 
package:flutter/…/widgets/framework.dart:4502
#4      StatefulElement.performRebuild 
package:flutter/…/widgets/framework.dart:4675
...

После использования этого кода

class DonorFormWrapper extends StatefulWidget{

  @override
  _DonorFormWrapperState createState() => _DonorFormWrapperState();
}

class _DonorFormWrapperState extends State<DonorFormWrapper>{
  Future<dynamic> _initUserFuture;
  bool before;

  @override
  void initState() {
    super.initState();
    final DonorAuthService _auth = DonorAuthService();
    final user = Provider.of<DonorUser>(context);

    print(user.uid);
    _initUserFuture = _auth.getDatabaseInstance(user.uid);
  }

  @override
  Widget build(BuildContext context) {
    return FutureBuilder(
      future: _initUserFuture,
      builder: (context, snapshot) {
        if (snapshot.connectionState == ConnectionState.done) {
          if (snapshot.data['name'] == 'name') {
            before = true;
            print(before);
            return DonorFormHomeBefore();
          } else {
            before = false;
            print(before);
            return DonorFormHomeAfter();
          }
        } else {
          return Center(
            child: CircularProgressIndicator(),
          );
        }
      },
    );
  }
}

Это ошибка, которую я получил

Exception caught by widgets library ═══════════════════════════════════
The following assertion was thrown building DefaultTextStyle(debugLabel: (englishLike body1 2014).merge(blackMountainView bodyText2), inherit: false, color: Color(0xdd000000), family: Roboto, size: 14.0, weight: 400, baseline: alphabetic, decoration: TextDecoration.none, softWrap: wrapping at box width, overflow: clip):
dependOnInheritedWidgetOfExactType<_InheritedProviderScope<DonorUser>>() or dependOnInheritedElement() was called before _DonorFormWrapperState.initState() completed.

When an inherited widget changes, for example if the value of Theme.of() changes, its dependent widgets are rebuilt. If the dependent widget's reference to the inherited widget is in a constructor or an initState() method, then the rebuilt dependent widget will not reflect the changes in the inherited widget.

Typically references to inherited widgets should occur in widget build() methods. Alternatively, initialization based on inherited widgets can be placed in the didChangeDependencies method, which is called after initState and whenever the dependencies change thereafter.

The relevant error-causing widget was
    PersistentTabView 
lib\…\Home\donor_home.dart:68
When the exception was thrown, this was the stack
#0      StatefulElement.dependOnInheritedElement.<anonymous closure> 
package:flutter/…/widgets/framework.dart:4761
#1      StatefulElement.dependOnInheritedElement 
package:flutter/…/widgets/framework.dart:4804
#2      Provider.of 
package:provider/src/provider.dart:213
#3      _DonorFormWrapperState.initState 
package:PlasmaBank/…/Home/donor_form_wrapper.dart:26
#4      StatefulElement._firstBuild 
package:flutter/…/widgets/framework.dart:4640
...

Вот ошибка, которую я получаю от своего эмулятора

import 'package:flutter/material.dart';

class DonorFormHomeAfter extends StatefulWidget {
  @override
  _DonorFormHomeAfterState createState() => _DonorFormHomeAfterState();
}

class _DonorFormHomeAfterState extends State<DonorFormHomeAfter> {
  @override
  Widget build(BuildContext context) {
    return Container(
      child: Center(
        child: Text('Data has been saved!'),
      ),
    );
  }
}
import 'package:PlasmaBank/screens/Donor/Home/donor_home_form.dart';
import 'package:flutter/material.dart';

class DonorFormHomeBefore extends StatefulWidget {
  @override
  _DonorFormHomeBeforeState createState() => _DonorFormHomeBeforeState();
}

class _DonorFormHomeBeforeState extends State<DonorFormHomeBefore> {
  @override
  Widget build(BuildContext context) {
    return Container(
      child: Center(
        child: RaisedButton(
          child: Text('Create New Donor'),
          onPressed: () {
            Navigator.push(
                  context,
                  MaterialPageRoute(builder: (context) => DonorForm()),
                  );
          },
        ),
        ),
    );
  }
}
class DonorWrapper extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final user = Provider.of<DonorUser>(context);
    print(user);

    // return either the Home or Authenticate widget
    if (user == null){
      return DonorAuthenticate();
    } else {
      return DonorHome();
    }
  }
}

Код сейчас работает нормально, кроме случаев, когда я нажимаю кнопку формы из панели навигации, появляется ошибка на мгновение, и ошибка немедленно исчезает. Вот подробности:

class DonorFormWrapper extends StatefulWidget{

  @override
  _DonorFormWrapperState createState() => _DonorFormWrapperState();
}

class _DonorFormWrapperState extends State<DonorFormWrapper>{

  bool before;

  @override
  Widget build(BuildContext context) {

    final DonorAuthService _auth = DonorAuthService();
    final user = Provider.of<DonorUser>(context);

    return FutureBuilder(
      future: _auth.getDatabaseInstance(user.uid),
      builder: (BuildContext context, AsyncSnapshot<dynamic> snapshot){
          if(snapshot.data['name']== 'name') {
            return DonorFormHomeBefore();
          }
          else if (snapshot.data['name'] != 'name') {
            return DonorFormHomeAfter();
          }
          else {
            return Center(
                          child: CircularProgressIndicator(

              ),
            );
          }
      }
      );
  }
}
Exception caught by widgets library ═══════════════════════════════════
The following NoSuchMethodError was thrown building FutureBuilder<dynamic>(dirty, state: _FutureBuilderState<dynamic>#f8ba4):
The method '[]' was called on null.
Receiver: null
Tried calling: []("name")

The relevant error-causing widget was
    FutureBuilder<dynamic> 
package:PlasmaBank/…/Home/donor_form_wrapper.dart:32
When the exception was thrown, this was the stack
#0      Object.noSuchMethod  (dart:core-patch/object_patch.dart:53:5)
#1      _DonorFormWrapperState.build.<anonymous closure> 
package:PlasmaBank/…/Home/donor_form_wrapper.dart:35
#2      _FutureBuilderState.build 
package:flutter/…/widgets/async.dart:732
#3      StatefulElement.build 
package:flutter/…/widgets/framework.dart:4619
#4      ComponentElement.performRebuild 
package:flutter/…/widgets/framework.dart:4502
...

Ответы [ 2 ]

0 голосов
/ 18 июня 2020

Перед выполнением каких-либо действий проверьте, есть ли на снимке данные.

import 'package:flutter/material.dart';

class DonorFormWrapper extends StatefulWidget {
  @override
  _DonorFormWrapperState createState() => _DonorFormWrapperState();
}

class _DonorFormWrapperState extends State<DonorFormWrapper> {
  @override
  Widget build(BuildContext context) {
    final DonorAuthService _auth = DonorAuthService();
    final user = Provider.of<DonorUser>(context);
    return FutureBuilder(
        future: _auth.getDatabaseInstance(user.uid),
        builder: (BuildContext context, AsyncSnapshot<dynamic> snapshot) {
          if (snapshot.hasData && snapshot.data != null) {
            if (snapshot.data['name'] == 'name') {
              return DonorFormHomeBefore();
            }
            return DonorFormHomeAfter();
          } else {
            return Center(
              child: CircularProgressIndicator(),
            );
          }
        });
  }
}
0 голосов
/ 18 июня 2020

Когда я тестирую ваш короткий код, он работает хорошо.
Похоже, проблема находится в другом источнике.
DonorFormHomeBefore () или DonorFormHomeAfter () enter image description here

import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';

import 'package:flutter_staggered_grid_view/flutter_staggered_grid_view.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      title: "landRegistration App",
      theme: new ThemeData(primarySwatch: Colors.amber),
      home: DonorFormWrapper(),
    );
  }
}

class DonorFormWrapper extends StatefulWidget {
  @override
  _DonorFormWrapperState createState() => _DonorFormWrapperState();
}

class _DonorFormWrapperState extends State<DonorFormWrapper> {
  Future<dynamic> _initUserFuture;
  bool before;

  @override
  void initState() {
    super.initState();

    _initUserFuture = getTest();
  }

  Future<dynamic> getTest() async {
    return await Future.value(42).timeout(const Duration(seconds: 3));
  }

  @override
  Widget build(BuildContext context) {
    return FutureBuilder(
      future: _initUserFuture,
      builder: (context, snapshot) {
        if (snapshot.connectionState == ConnectionState.done) {
          print(snapshot.data);
          if (snapshot.data == 42) {
            before = true;
            print(before);
            return Container(child: Text('1'));
          } else {
            before = false;
            print(before);
            return Container(child: Text('2'));
          }
        } else {
          return Center(
            child: CircularProgressIndicator(),
          );
        }
      },
    );
  }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...