10 промтов для Flutter: от виджетов до state management и анимаций
Flutter — это популярный фреймворк для создания кроссплатформенных приложений. С помощью правильно составленных промтов вы можете ускорить разработку, автоматизировать рутинные задачи и углубить понимание фреймворка. В этой подборке мы собрали 10 практичных промтов, которые охватывают виджеты, анимации, управление состоянием и тестирование. Каждый промт сопровождается примером использования и кодом, который легко адаптировать под свой проект.
Эти промты основаны на официальной документации Flutter (Flutter Widgets, State Management) и опыте разработчиков, поэтому вы можете доверять их корректности.
1. Генерация виджета с валидацией email
Промт: Сгенерируй Flutter виджет для ввода email с валидацией. Используй TextFormField, Form и соответствующие валидаторы. Предоставь полный код на Dart с комментариями.
Зачем: Этот промт позволяет быстро получить рабочий код формы с валидацией, не тратя время на написание рутины.
Пример использования: Вы копируете промт в AI-инструмент, получаете код, вставляете в свой проект. Ниже — один из вариантов результата.
import 'package:flutter/material.dart';
class EmailForm extends StatefulWidget {
@override
_EmailFormState createState() => _EmailFormState();
}
class _EmailFormState extends State<EmailForm> {
final _formKey = GlobalKey<FormState>();
final _emailController = TextEditingController();
@override
void dispose() {
_emailController.dispose();
super.dispose();
}
String? _validateEmail(String? value) {
if (value == null || value.isEmpty) {
return 'Введите email';
}
final emailRegex = RegExp(r'^[^@]+@[^@]+\.[^@]+$');
if (!emailRegex.hasMatch(value)) {
return 'Введите корректный email';
}
return null;
}
@override
Widget build(BuildContext context) {
return Form(
key: _formKey,
child: TextFormField(
controller: _emailController,
decoration: const InputDecoration(labelText: 'Email'),
validator: _validateEmail,
),
);
}
}
2. Разница между StatefulWidget и StatelessWidget
Промт: Объясни разницу между StatefulWidget и StatelessWidget в Flutter. Приведи наглядный пример для каждого случая.
Зачем: Понимание этой разницы — основа Flutter-разработки. Промт помогает быстро получить объяснение с примерами.
Пример использования: Вы получаете развернутый ответ. Ключевое отличие: StatelessWidget неизменяем, а StatefulWidget хранит состояние и может перестраиваться при его изменении.
// StatelessWidget — статичный виджет
class MyStateless extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Text('Я не меняюсь');
}
}
// StatefulWidget — виджет с состоянием
class MyStateful extends StatefulWidget {
@override
_MyStatefulState createState() => _MyStatefulState();
}
class _MyStatefulState extends State<MyStateful> {
int _counter = 0;
@override
Widget build(BuildContext context) {
return Column(
children: [
Text('Счётчик: $_counter'),
ElevatedButton(
onPressed: () => setState(() => _counter++),
child: Text('Увеличить'),
),
],
);
}
}
3. Анимация появления элемента
Промт: Напиши код для плавного появления элемента при нажатии кнопки. Используй AnimatedOpacity и AnimatedContainer.
Зачем: Анимации делают интерфейс живым. Этот промт даёт рабочий пример для встраивания анимаций.
Пример использования: Код кнопки, которая плавно показывает/скрывает блок и меняет его размер.
import 'package:flutter/material.dart';
class AnimatedDemo extends StatefulWidget {
@override
_AnimatedDemoState createState() => _AnimatedDemoState();
}
class _AnimatedDemoState extends State<AnimatedDemo> {
bool _visible = false;
@override
Widget build(BuildContext context) {
return Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
ElevatedButton(
onPressed: () => setState(() => _visible = !_visible),
child: Text('Показать/скрыть'),
),
AnimatedOpacity(
opacity: _visible ? 1.0 : 0.0,
duration: Duration(milliseconds: 500),
child: AnimatedContainer(
duration: Duration(milliseconds: 500),
width: _visible ? 200 : 100,
height: _visible ? 200 : 100,
color: Colors.blue,
child: Center(child: Text('Контент')),
),
),
],
);
}
}
4. Переход с setState на Provider
Промт: Как перевести Flutter-приложение с setState на Provider? Покажи пример с ChangeNotifier.
Зачем: Provider — популярное решение для управления состоянием. Промт поможет мигрировать существующий код.
Пример использования: Создаем модель-счётчик, подключаем ChangeNotifier и используем его в виджетах с помощью Provider.of.
// 1. Модель
class CounterModel extends ChangeNotifier {
int _count = 0;
int get count => _count;
void increment() {
_count++;
notifyListeners();
}
}
// 2. В main.dart
void main() {
runApp(
ChangeNotifierProvider(
create: (_) => CounterModel(),
child: MyApp(),
),
);
}
// 3. В виджете
class CounterPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
final counter = Provider.of<CounterModel>(context);
return Scaffold(
body: Center(
child: Text('${counter.count}'),
),
floatingActionButton: FloatingActionButton(
onPressed: counter.increment,
child: Icon(Icons.add),
),
);
}
}
5. Riverpod для списка задач
Промт: Создай пример использования Riverpod для управления состоянием списка задач. Используй StateProvider и FutureProvider.
Зачем: Riverpod — развивающаяся библиотека управления состоянием, которая устраняет недостатки Provider.
Пример использования: StateProvider для списка, FutureProvider для асинхронной загрузки.
final tasksProvider = StateProvider<List<String>>((ref) => []);
final fetchTasksProvider = FutureProvider<List<String>>((ref) async {
await Future.delayed(Duration(seconds: 2));
return ['Задача 1', 'Задача 2'];
});
class TasksList extends ConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
final tasks = ref.watch(tasksProvider);
final asyncTasks = ref.watch(fetchTasksProvider);
return Column(
children: [
Expanded(
child: asyncTasks.when(
data: (data) => ListView.builder(
itemCount: data.length,
itemBuilder: (ctx, i) => ListTile(title: Text(data[i])),
),
loading: () => CircularProgressIndicator(),
error: (err, _) => Text('Ошибка: $err'),
),
),
],
);
}
}
6. BLoC для аутентификации
Промт: Напиши BLoC-класс для аутентификации пользователя, используя Equatable и dart_bloc.
Зачем: BLoC (Business Logic Component) — ещё один мощный подход к управлению состоянием, часто используется в больших проектах.
Пример использования: Событие и состояние, BLoC-класс с обработкой.
// Событие
abstract class AuthEvent extends Equatable {
const AuthEvent();
@override
List<Object?> get props => [];
}
class LoginEvent extends AuthEvent {
final String email;
final String password;
const LoginEvent(this.email, this.password);
@override
List<Object?> get props => [email, password];
}
// Состояние
abstract class AuthState extends Equatable {
const AuthState();
@override
List<Object?> get props => [];
}
class AuthInitial extends AuthState {}
class AuthLoading extends AuthState {}
class AuthSuccess extends AuthState {}
class AuthFailure extends AuthState {
final String message;
const AuthFailure(this.message);
@override
List<Object?> get props => [message];
}
// BLoC
class AuthBloc extends Bloc<AuthEvent, AuthState> {
AuthBloc() : super(AuthInitial()) {
on<LoginEvent>((event, emit) async {
emit(AuthLoading());
try {
// Представим, что здесь вызов API
await Future.delayed(Duration(seconds: 1));
emit(AuthSuccess());
} catch (e) {
emit(AuthFailure(e.toString()));
}
});
}
}
7. Бесконечный список с пагинацией
Промт: Создай кастомный виджет для бесконечного списка с загрузкой данных, используя ScrollController и FutureBuilder.
Зачем: Пагинация необходима при работе с большими данными. Этот промт даёт готовый шаблон.
Пример использования: При прокрутке вниз подгружается следующая страница.
import 'package:flutter/material.dart';
class PaginatedList extends StatefulWidget {
@override
_PaginatedListState createState() => _PaginatedListState();
}
class _PaginatedListState extends State<PaginatedList> {
final _scrollController = ScrollController();
final _items = <String>[];
bool _isLoading = false;
int _page = 1;
@override
void initState() {
super.initState();
_scrollController.addListener(_onScroll);
_loadMore();
}
Future<void> _loadMore() async {
if (_isLoading) return;
setState(() => _isLoading = true);
// Имитация запроса
await Future.delayed(Duration(seconds: 2));
final newItems = List.generate(10, (i) => 'Элемент ${_page * 10 + i}');
setState(() {
_items.addAll(newItems);
_page++;
_isLoading = false;
});
}
void _onScroll() {
if (_scrollController.position.pixels >=
_scrollController.position.maxScrollExtent - 100) {
_loadMore();
}
}
@override
Widget build(BuildContext context) {
return ListView.builder(
controller: _scrollController,
itemCount: _items.length + (_isLoading ? 1 : 0),
itemBuilder: (context, index) {
if (index >= _items.length) {
return Center(child: CircularProgressIndicator());
}
return ListTile(title: Text(_items[index]));
},
);
}
@override
void dispose() {
_scrollController.dispose();
super.dispose();
}
}
8. Юнит-тесты для валидации и виджета-счётчика
Промт: Напиши юнит-тесты для функции валидации email и для простого виджета-счётчика, используя flutter_test.
Зачем: Тестирование — важная часть разработки. Промт помогает быстро создать тестовые сценарии.
Пример использования: Тест для валидатора и тест виджета с тапом.
// Функция валидации (вынесена отдельно)
String? validateEmail(String? value) {
if (value == null || value.isEmpty) return 'Введите email';
final regex = RegExp(r'^[^@]+@[^@]+\.[^@]+$');
return regex.hasMatch(value) ? null : 'Некорректный email';
}
// Тесты
void main() {
test('Валидатор email принимает корректный адрес', () {
expect(validateEmail('test@example.com'), isNull);
});
test('Валидатор email отклоняет некорректный адрес', () {
expect(validateEmail('invalid'), isNotNull);
});
testWidgets('Счётчик увеличивается по нажатию', (tester) async {
await tester.pumpWidget(MyStateful());
expect(find.text('Счётчик: 0'), findsOneWidget);
await tester.tap(find.text('Увеличить'));
await tester.pump();
expect(find.text('Счётчик: 1'), findsOneWidget);
});
}
9. Оптимизация производительности
Промт: Проанализируй этот Flutter-код и предложи оптимизации для уменьшения перестроений: [вставить ваш код].
Зачем: Оптимизация помогает повысить плавность UI. Промт даёт рекомендации по использованию const, split в виджеты, ключей.
Пример использования: Вы вставляете свой код, AI предлагает:
- добавлять
constк неизменным виджетам; - выносить часто перестраиваемые части в отдельные методы с
constконструкторами; - использовать
RepaintBoundaryдля сложных анимаций.
Пример до/после:
// До оптимизации
@override
Widget build(BuildContext context) {
return Column(
children: [
Text('Заголовок'),
Text('Подзаголовок'),
],
);
}
// После оптимизации
@override
Widget build(BuildContext context) {
return const Column(
children: [
Text('Заголовок'),
Text('Подзаголовок'),
],
);
}
10. Создание темы оформления
Промт: Создай тему приложения с помощью ThemeData, включая тёмный режим, цвета и шрифты.
Зачем: Единый стиль приложения создаёт положительное впечатление у пользователей.
Пример использования: Определяем светлую и тёмную темы.
class AppTheme {
static ThemeData get lightTheme => ThemeData(
primarySwatch: Colors.blue,
brightness: Brightness.light,
appBarTheme: AppBarTheme(
backgroundColor: Colors.blue,
foregroundColor: Colors.white,
),
);
static ThemeData get darkTheme => ThemeData(
primarySwatch: Colors.indigo,
brightness: Brightness.dark,
appBarTheme: AppBarTheme(
backgroundColor: Colors.indigo,
foregroundColor: Colors.white,
),
);
}
// В MaterialApp
MaterialApp(
theme: AppTheme.lightTheme,
darkTheme: AppTheme.darkTheme,
)
Заключение
Эти 10 промтов — лишь малая часть того, что можно использовать в Flutter-разработке. Адаптируйте их, комбинируйте, пробуйте новые варианты, и вы увидите, как AI ускоряет вашу работу. Но помните: всегда проверяйте сгенерированный код и понимайте, что он делает.
Подписывайтесь на наш блог, чтобы получать новые подборки промтов и практические руководства по Flutter. Оставляйте комментарии — мы обратной связью делаем контент лучше.
Комментарии