#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
, которая выполняет обратный вызов. Тем не менее, ваша функция имеет к ней доступ, потому что она ее «захватила». Замыкание — это функция плюс среда. В вашем коде ясно, что это за функция. Среда — это дополнительный бит, который позволяет этой функции подключаться к переменной-члену вашего виджета с отслеживанием состояния.