ProviderNotFoundException (Ошибка: не удалось найти правильный поставщик <LayoutData>над этим виджетом SchedulingPage с использованием layoutBuilder - PullRequest
0 голосов
/ 12 апреля 2020

Получено исключение providerNotFoundException, и я подозреваю, что в приведенном ниже коде есть несоответствие контекста, но мне трудно его увидеть. Как я понимаю, проблемы с BuilderContext возникают, когда метод .of выполняется внутри того же метода сборки, но я не вижу, чтобы это происходило в этом случае. Некоторые из методов Provider.of работают нормально, как указано в приведенном ниже коде, но как только вызывается SchedulingPage, методы Provider.of перестают работать.

В чем здесь проблема?

Редактировать: я обновил, чтобы использовать мой полный код ниже: Вот полная ошибка: ProviderNotFoundException (Ошибка: Не удалось найти правильного провайдера над этим виджетом LoginForm

void main() {
  runApp(
    Home(),
  );
}

class Home extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MultiProvider(
      providers: [
        // ChangeNotifierProvider(create: (context) => CalendarData()),
        ChangeNotifierProvider(create: (context) => LayoutData()),
      ],
      child: MyApp(),
    );
  }
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: SafeArea(
        child: LayoutBuilder(
            builder: (BuildContext context, BoxConstraints constraints) {
          print("constraints: $constraints");
          Size mediaSize = MediaQuery.of(context).size;
          double safeAreaSize = mediaSize.height - constraints.maxHeight;
          Provider.of<LayoutData>(context).safeAreaDiff = safeAreaSize;
          Provider.of<LayoutData>(context).safeArea = constraints;
          Provider.of<LayoutData>(context).mediaArea = mediaSize;
          var test = Provider.of<LayoutData>(context).mediaArea.width;
          print(test);  // this works

          return Scaffold(body: LoginScreen());
        }),
      ),
    );
  }
}

    class LoginScreen extends StatelessWidget {
      const LoginScreen({Key key}) : super(key: key);

      @override
      Widget build(BuildContext context) {
        double test = Provider.of<LayoutData>(context).mediaArea.width;
        print("test: $test");  // this works
        return LoginForm();
      }
    }

    class LoginForm extends StatefulWidget {
      LoginForm({Key key}) : super(key: key);

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

    class _LoginFormState extends State<LoginForm> {
      @override
      Widget build(BuildContext context) {
        double width = Provider.of<LayoutData>(context).mediaArea.width; // The code fails here
        print('width: $width');
        return Text("this is where it fails ^^^^^^^^");
      }
    }

    class LayoutData with ChangeNotifier {
      double safeAreaDiff = 0.0;
      BoxConstraints safeArea;
      Size mediaArea;

      LayoutData() {
        initializeApp();
      }

      void initializeApp() {
        print("layout initialized");
      }
    }

Ответы [ 3 ]

1 голос
/ 12 апреля 2020

Вы не можете получить доступ к провайдеру того же класса, в котором вы создаете. Это должен быть родительский виджет.

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

class Home extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MultiProvider(
      providers: [
        ChangeNotifierProvider(create: (context) => CalendarData()),
        ChangeNotifierProvider(create: (context) => LayoutData()),
      ],
      child: MyApp(),
    );
  }
}


class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: SafeArea(
        child: LayoutBuilder(
            builder: (BuildContext context, BoxConstraints constraints) {
          print("constraints: $constraints");
          Size mediaSize = MediaQuery.of(context).size;
          double safeAreaSize =
              mediaSize.height - constraints.maxHeight; // works
          Provider.of<LayoutData>(context).safeAreaDiff =
              safeAreaSize; // works
          Provider.of<LayoutData>(context).safeArea = constraints; // works
          Provider.of<LayoutData>(context).mediaArea = mediaSize; // works
          Provider.of<CalendarData>(context).working = "beer"; // works
          print(Provider.of<CalendarData>(context).working); // works

          return Scaffold(body: SchedulingPage());
        }),
      ),
    );
  }
}

Вывод:

Performing hot restart...                                               
Restarted application in 1,181ms.
I/flutter (25187): constraints: BoxConstraints(w=411.4, h=659.4)
I/flutter (25187): layout initialized
I/flutter (25187): 411.42857142857144
I/flutter (25187): test: 411.42857142857144
I/flutter (25187): width: 411.42857142857144
0 голосов
/ 14 апреля 2020

Я публикую это на случай, если у кого-то возникнет та же проблема, что и у меня. Оказалось, что проблема не была решена выбранным решением. Код, как написано, должен был работать. Однако в этом случае решение было трудно найти. Оказалось, что сам импорт был некорректным. Было два импорта класса данных провайдера, например:

import 'package:myProject/providers/CalendarData.dart'; 

и

import 'package:gcfdlayout2/Providers/CalendarData.dart';

Эта двусмысленность запутала IDE, я полагаю, и, хотя она не дала мне любые ошибки во время сборки, это происходило во время выполнения, но «не удалось найти провайдера» заставило меня предположить, что он не может найти провайдера в дереве, а не в самом коде.

Способ, которым я наконец, выяснилось, что это использовать другие методы запуска кода. Первоначально я использовал только код Visual Studio, но я никогда не получал ошибок, свидетельствующих о том, что это проблема импорта. Я изменил на Android Studio, и он сообщил мне, что для класса CalendarData было два импорта.

0 голосов
/ 12 апреля 2020

Вы пытались разместить MultiProvider () над MaterialApp ()?

...