Ошибка: в инициализаторах доступны только статические члены. Что это значит? - PullRequest
0 голосов
/ 03 мая 2018

У меня есть что-то вроде этого. Мне трудно понять эту ошибку. Почему доступ к filterController здесь дает эту ошибку здесь? но это не дает этой ошибки, если я перемещаю текущее целое создание TextFormField (между комментариями A и B) внутри метода сборки? Как перемещение всего TextFormField в методе сборки делает filterController статическим и решает эту проблему?

class AppHomeState extends State<AppHome> with SingleTickerProviderStateMixin
{

    TabController _tabController;
    final filterController = new TextEditingController(text: "Search");
        //----A
        TextFormField email = new TextFormField(
        keyboardType: TextInputType.emailAddress,
        controller: filterController,    ------>ERROR : Error: Only static members can be accessed in initializers
        );
       //----B

  @override
    Widget build(BuildContext context)
    {
        return new Scaffold(
                appBar: new AppBar(..),
        );
    }
}

Как я могу решить эту проблему?

Ответы [ 3 ]

0 голосов
/ 03 мая 2018
class AppHomeState extends State<AppHome> with SingleTickerProviderStateMixin {

    TabController _tabController;
    final filterController = new TextEditingController(text: "Search");
    TextFormField email = ...

... является инициализатором, и на данный момент нет доступа к this. Инициализаторы выполняются до конструктора, но доступ к this разрешен только после завершения вызова суперконструктора (неявного в вашем примере). Поэтому только в теле конструктора (или позже) разрешен доступ к this.

Вот почему вы получаете сообщение об ошибке:

controller: filterController,

доступ this.filterController (this неявно, если вы не пишете это явно).

Чтобы обойти вашу проблему (предполагая, что email должно быть final), вы можете использовать конструктор фабрики и список инициализатора конструктора:

class AppHomeState extends State<AppHome> with SingleTickerProviderStateMixin {
  factory SingleTickerProviderStateMixin() => 
      new SingleTickerProviderStateMixin._(new TextEditingController(text: "Search"));

  SingleTickerProviderStateMixin._(TextEditingController textEditingController) : 
      this.filterController = textEditingController,   
      this.email = new TextFormField(
        keyboardType: TextInputType.emailAddress,
        controller: textEditingController);

  TabController _tabController;
  final filterController;
  final TextFormField email;

или когда поле email не обязательно должно быть окончательным email можно инициализировать в списке инициализатора конструктора:

class AppHomeState extends State<AppHome> with SingleTickerProviderStateMixin {

  SingleTickerProviderStateMixin() {
    email = new TextFormField(
        keyboardType: TextInputType.emailAddress,
        controller: filterController,
    );
  }

  TabController _tabController;
  final filterController = new TextEditingController(text: "Search");
  TextFormField email;

но в виджетах Flutter initState обычно используется для этого

class AppHomeState extends State<AppHome> with SingleTickerProviderStateMixin {

  @override
  void initState() {
    super.initState();
    email = new TextFormField(
        keyboardType: TextInputType.emailAddress,
        controller: filterController,
    );
  }

  TabController _tabController;
  final filterController = new TextEditingController(text: "Search");
  TextFormField email; 
0 голосов
/ 05 января 2019

Вы можете сохранить это как метод:

Widget getEmailController(){
return new
 TextFormField email = new TextFormField(
        keyboardType: TextInputType.emailAddress,
        controller: filterController,
        );
}

и используйте его в пользовательском интерфейсе:

body: Container(
child: getEmailController();
)
0 голосов
/ 03 мая 2018

Вы можете преобразовать эту переменную в функцию, и вы можете использовать контекст в параметрах этой функции.

Пример

Widget myDialog (BuildContext context) {
  return new Scaffold(
    backgroundColor: Colors.white,
    body: new Center(
      child: new Column(
        children: <Widget>[
          new Text("Invalid Username/Password"),
          new Text("Please verify your login credentials"),
          new RaisedButton(
            child: new Text("Ok"),
            onPressed:() {
              Navigator.pop(context);//Error : Only static members can be accessed in initializers
            }
          ),
        ],
      ),
    )
  );
}

// Using if you are doing in a class
this.myDialog(context);

// Using if you are using a global function
myDialog(context);

Но, я думаю, вы хотите показать сообщение об ошибке. Таким образом, вы можете сделать это с помощью диалога, а не страницы. Это более эффективно, потому что вы можете указать свое диалоговое окно с помощью кнопок или сообщений, и вы можете использовать это диалоговое окно ошибки везде Давайте посмотрим мою глобальную вспомогательную функцию для отображения сообщений об ошибках.

void showError(BuildContext context, String error) {
  showSnackBar(
    context,
    new Text(
      'Error',
      style: new TextStyle(color: Theme.of(context).errorColor),
    ),
    content: new SingleChildScrollView(
      child: new Text(error)
    ),
    actions: <Widget>[
      new FlatButton(
        child: new Text(
          'Ok',
          style: new TextStyle(
            color: Colors.white
          ),
        ),
        onPressed: () {
          Navigator.of(context).pop();
        },
        color: Theme.of(context).errorColor,
      ),
    ]
  );
}

// Using in everywhere
showError(context, 'Sample Error');
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...