Путаница в анонимных функциях Dart

#function #flutter #dart #anonymous-function

#функция #флаттер #dart #анонимная функция

Вопрос:

Я хотел бы получить объяснение анонимных функций в Dart и того, как передаются в качестве аргументов другим функциям.

Приведенный ниже пример взят из программы «Напишите свое первое приложение» на flutter.dev.

 Widget _buildSuggestions() {
  return ListView.builder(
      padding: const EdgeInsets.all(16.0),
      itemBuilder:  (context, i) {
        if (i.isOdd) return Divider(); 

        final index = i ~/ 2; 
        if (index >= _suggestions.length) {
          _suggestions.addAll(generateWordPairs().take(10)); 
        }
        return _buildRow(_suggestions[index]);
      });
}
  

Анонимной функцией здесь является itemBuilder . Ее тип {(BuildContext, int) → Widget itemBuilder} .

Если бы ее тип был {() → Widget itemBuilder} , я мог бы понять, что во время выполнения будет выполняться тело функции. Но теперь с аргументами я не понимаю, как BuildContext и int будут предоставлены функции.

Ответ №1:

В конструкторе ListView вы передаете функцию, которую будет содержать представление списка, возможно, как вызываемую некоторую переменную экземпляра builderFunc . В какой-то момент в будущем представлению списка будет предложено выполнить сборку, и ему нужно будет создать своих дочерних элементов. Это будет сделано путем вызова builderFunc следующим образом:

 Widget jthChild = builderFunc(ctx, j);
  

где ctx и j являются локальными переменными в области видимости вызывающего объекта (метода в ListView ). builderFunc (ваша анонимная функция) создаст и вернет j -й виджет, используя контекст сборки, переданный ему в виде списка. Представление списка вызовет вашу функцию несколько раз с разными значениями j .

Комментарии:

1. Спасибо за четкий ответ. Я думаю, это элементарный вопрос для тех, кто разбирается в функциональном программировании. Еще одна вещь об этой функции, которую я передаю в конструкторе ListView… Это и есть закрытие?

2. В значительной степени, да. В вашей функции builder вы получаете доступ к _suggestions , которая не является локальной для функции (в отличие от context и i , которые являются фактическими параметрами). Также это не часть ListView , которая выполняет обратный вызов. Тем не менее, ваша функция имеет к ней доступ, потому что она ее «захватила». Замыкание — это функция плюс среда. В вашем коде ясно, что это за функция. Среда — это дополнительный бит, который позволяет этой функции подключаться к переменной-члену вашего виджета с отслеживанием состояния.