Ошибка: не удалось найти правильную ScopedModel при использовании ScopedModel.of <MyModel>(контекст) - PullRequest
0 голосов
/ 26 апреля 2019

Мне, как стороннему наблюдателю, изучающему управление состоянием флаттера, мне понравилась идея использовать scoped_model для управления состоянием, как рекомендовано в flutter.dev . Я переписал счетчик приложений. Я могу получить доступ к свойствам модели с помощью ScopedModelDescendant<CounterModel>, но у меня возникают проблемы с доступом к свойствам модели с помощью ScopedModel.of<CounterModel>(context). Может кто-нибудь посоветовать, пожалуйста, что я могу делать не так? У меня есть догадка, что это может быть, где ScopedModel в моем дереве виджетов. Мой код и сообщение об ошибке следующие.

main.dart

import 'package:flutter/material.dart';
import 'package:scoped_model/scoped_model.dart';
import 'package:second/model/counter_model.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  Widget build(context) {
    return ScopedModel(
      model: new CounterModel(),
      child: Scaffold(
          appBar: AppBar(
            title: Text('ScopedModel'),
          ),
          body: ScopedModelDescendant<CounterModel>(
            builder: (context, child, value) {
              return Text("Pressed ${value.counter} times");
            },
          ),
          floatingActionButton: buildFab1()),
    );
  }

  Widget buildFab1() {
    return ScopedModelDescendant<CounterModel>(
      builder: (context, child, model) => FloatingActionButton(
            child: Icon(Icons.add),
            onPressed: model.incrementCounter,
          ),
    );
  }

  Widget buildFab2(BuildContext context) {
    return FloatingActionButton(
      child: Icon(Icons.add),
      onPressed: ScopedModel.of<CounterModel>(context).incrementCounter,
    );
  }
}

модель / counter_model.dart

import 'package:scoped_model/scoped_model.dart';

class CounterModel extends Model {
  int _counter = 0;

  int get counter => _counter;

  void incrementCounter() {
    _counter++;
    notifyListeners();
  }
}

В main.dart, если я использую buildFab2(context) вместо buildFab1(), я получаю следующую ошибку


flutter: The following ScopedModelError was thrown building ScopedModelDescendant<Model>(dirty):
flutter: Error: Could not find the correct ScopedModel.
flutter:
flutter: To fix, please:
flutter:
flutter:   * Provide types to ScopedModel<MyModel>
flutter:   * Provide types to ScopedModelDescendant<MyModel>
flutter:   * Provide types to ScopedModel.of<MyModel>()
flutter:   * Always use package imports. Ex: `import 'package:my_app/my_model.dart';
flutter:

Я взглянул на несколько ТАК вопросов, но ни один не помог.

1 Ответ

1 голос
/ 26 апреля 2019

Да, потому что context, который вы передадите, не будет иметь ScopedModel из CounterModel.

Что вы можете сделать, это обернуть ваш buildFab2 в виджет Builder, который будетпредоставить вам context с ScopedModel с CounterModel в качестве родителя.

Как:

Builder(
    builder: (context){
      return buildFab2(context);
    },
  )

Ваше приложение будет выглядеть так:

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  Widget build(context) {
    return ScopedModel(
      model: new CounterModel(),
      child: Scaffold(
        appBar: AppBar(
          title: Text('ScopedModel'),
        ),
        body: ScopedModelDescendant<CounterModel>(
          builder: (context, child, value) {
            return Text("Pressed ${value.counter} times");
          },
        ),
        floatingActionButton: Builder(
          builder: (context) {
            // return buildFab1() if fab one required
            return buildFab2(context);
          },
        ),
      ),
    );
  }

  Widget buildFab1() {
    return ScopedModelDescendant<CounterModel>(
      builder: (context, child, model) => FloatingActionButton(
            child: Icon(Icons.add),
            onPressed: model.incrementCounter,
          ),
    );
  }

  Widget buildFab2(BuildContext context) {
    return FloatingActionButton(
      child: Icon(Icons.add),
      onPressed: ScopedModel.of<CounterModel>(context).incrementCounter,
    );
  }
}

Надеюсь, это поможет!

...