Flutter vs React Native: 12 промтов, которые превращают хаос нативных багов в работающий MVP за выходные

Вступление

Вы когда-нибудь ловили себя на том, что вместо написания бизнес-логики вы тонете в дебаге нативных модулей? Вчера вы боролись с PlatformException в Flutter на Android 14, сегодня — с NativeModule в React Native, который внезапно перестал работать на iOS 17. Знакомо? По данным опроса Stack Overflow Developer Survey 2025, около 40% разработчиков мобильных приложений называют кроссплатформенные фреймворки одновременно и спасением, и источником головной боли. И это не удивительно: разница в API, версиях ОС и поведении платформ съедает драгоценные часы.

Но что, если превратить эту боль в управляемый процесс? AI-ассистенты уже умеют генерировать код, но без правильных промтов они выдают шаблонные решения, которые не учитывают специфику Flutter или React Native. В этой подборке я собрал 12 промтов, проверенных на реальных проектах. Они разделены на три уровня: базовые (для быстрого старта), продвинутые (для работы с состоянием и навигацией) и экспертные (для нативных модулей и оптимизации). Каждый промт содержит задачу, готовый текст и пример результата. Вы сможете собрать MVP на двух платформах за выходные, а не за две недели.


Базовые промты: генерация экранов и UI

1. Генерация экрана с формой и валидацией

Задача: Создать экран регистрации с полями email и пароль, валидацией и адаптацией под iOS/Android.

Промт:

Ты — senior Flutter разработчик. Сгенерируй виджет RegistrationScreen с полями email и password, используя TextFormField. Добавь валидацию: email должен содержать @ и точку, пароль — минимум 8 символов. Кнопка "Зарегистрироваться" должна быть неактивна, пока форма не валидна. Учти различия: на iOS используй CupertinoTextField, на Android — Material TextField. Приведи полный код с комментариями.

Пример результата:

import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';

class RegistrationScreen extends StatefulWidget {
  @override
  _RegistrationScreenState createState() => _RegistrationScreenState();
}

class _RegistrationScreenState extends State<RegistrationScreen> {
  final _formKey = GlobalKey<FormState>();
  final _emailController = TextEditingController();
  final _passwordController = TextEditingController();
  bool _isValid = false;

  @override
  void initState() {
    super.initState();
    _emailController.addListener(_validate);
    _passwordController.addListener(_validate);
  }

  void _validate() {
    setState(() {
      _isValid = _formKey.currentState?.validate() ?? false;
    });
  }

  @override
  Widget build(BuildContext context) {
    final isIOS = Theme.of(context).platform == TargetPlatform.iOS;
    return Scaffold(
      appBar: AppBar(title: Text('Регистрация')),
      body: Form(
        key: _formKey,
        child: Padding(
          padding: EdgeInsets.all(16),
          child: Column(
            children: [
              isIOS
                  ? CupertinoTextField(
                      controller: _emailController,
                      placeholder: 'Email',
                      keyboardType: TextInputType.emailAddress,
                    )
                  : TextFormField(
                      controller: _emailController,
                      decoration: InputDecoration(labelText: 'Email'),
                      validator: (value) {
if (value == null

|| !value.contains('@') || !value.contains('.')) {
                          return 'Введите корректный email';
                        }
                        return null;
                      },
                    ),
              SizedBox(height: 16),
              // Аналогично для пароля
              ElevatedButton(
                onPressed: _isValid ? () {} : null,
                child: Text('Зарегистрироваться'),
              ),
            ],
          ),
        ),
      ),
    );
  }
}

2. Адаптивная навигация с BottomNavigationBar

Задача: Сделать нижнюю навигацию, которая выглядит нативно на iOS (TabBar) и Android (BottomNavigationBar).

Промт:

Создай кроссплатформенный виджет MainNavigation с тремя вкладками: Главная, Поиск, Профиль. На iOS используй CupertinoTabBar, на Android — BottomNavigationBar. Обеспечь сохранение состояния каждой вкладки. Напиши код для Flutter.

Пример результата:

class MainNavigation extends StatefulWidget {
  @override
  _MainNavigationState createState() => _MainNavigationState();
}

class _MainNavigationState extends State<MainNavigation> {
  int _currentIndex = 0;
  final _pages = [HomePage(), SearchPage(), ProfilePage()];

  @override
  Widget build(BuildContext context) {
    final isIOS = Theme.of(context).platform == TargetPlatform.iOS;
    return isIOS
        ? CupertinoTabScaffold(
            tabBar: CupertinoTabBar(
              items: [
                BottomNavigationBarItem(icon: Icon(Icons.home), label: 'Главная'),
                BottomNavigationBarItem(icon: Icon(Icons.search), label: 'Поиск'),
                BottomNavigationBarItem(icon: Icon(Icons.person), label: 'Профиль'),
              ],
              onTap: (index) => setState(() => _currentIndex = index),
            ),
            tabBuilder: (context, index) => _pages[index],
          )
        : Scaffold(
            body: _pages[_currentIndex],
            bottomNavigationBar: BottomNavigationBar(
              currentIndex: _currentIndex,
              onTap: (index) => setState(() => _currentIndex = index),
              items: [
                BottomNavigationBarItem(icon: Icon(Icons.home), label: 'Главная'),
                BottomNavigationBarItem(icon: Icon(Icons.search), label: 'Поиск'),
                BottomNavigationBarItem(icon: Icon(Icons.person), label: 'Профиль'),
              ],
            ),
          );
  }
}

3. Стилизация под платформу

Задача: Автоматически применять разные цвета и шрифты в зависимости от ОС.

Промт:

Напиши функцию getPlatformStyle(BuildContext context), которая возвращает TextStyle с разными параметрами для iOS (шрифт San Francisco, цвет синий) и Android (шрифт Roboto, цвет зелёный). Используй Theme.of(context).platform.

Пример результата:

TextStyle getPlatformStyle(BuildContext context) {
  final platform = Theme.of(context).platform;
  if (platform == TargetPlatform.iOS) {
    return TextStyle(fontFamily: 'San Francisco', color: Colors.blue);
  } else {
    return TextStyle(fontFamily: 'Roboto', color: Colors.green);
  }
}

Продвинутые промты: состояние и навигация

4. Управление состоянием с Provider

Задача: Реализовать счётчик с сохранением состояния между экранами.

Промт:

Создай ChangeNotifier CounterModel с полем count и методами increment/decrement. Настрой Provider в main.dart. Сделай два экрана: первый отображает счётчик и кнопки, второй — только значение. При переходе между экранами значение должно сохраняться.

Пример результата:

class CounterModel extends ChangeNotifier {
  int _count = 0;
  int get count => _count;
  void increment() { _count++; notifyListeners(); }
  void decrement() { _count--; notifyListeners(); }
}

void main() {
  runApp(
    ChangeNotifierProvider(
      create: (_) => CounterModel(),
      child: MyApp(),
    ),
  );
}

5. Навигация с передачей параметров

Задача: Перейти на экран деталей, передав объект.

Промт:

Настрой навигацию в Flutter: с экрана списка товаров перейти на экран деталей, передав объект Product. Используй MaterialPageRoute. Покажи, как принять параметр в DetailScreen.

Пример результата:

Navigator.push(
  context,
  MaterialPageRoute(builder: (context) => DetailScreen(product: product)),
);

class DetailScreen extends StatelessWidget {
  final Product product;
  DetailScreen({required this.product});
  @override
  Widget build(BuildContext context) {
    return Scaffold(appBar: AppBar(title: Text(product.name)));
  }
}

6. Асинхронная загрузка данных с индикатором

Задача: Загрузить список с API и показать CircularProgressIndicator, пока идёт загрузка.

Промт:

Создай экран, который при запуске делает GET-запрос к https://jsonplaceholder.typicode.com/posts и отображает список. Пока данные грузятся, показывай CircularProgressIndicator. При ошибке — SnackBar с сообщением. Используй FutureBuilder.

Пример результата:

FutureBuilder<List<dynamic>>(
  future: http.get(Uri.parse('https://jsonplaceholder.typicode.com/posts')).then((res) => json.decode(res.body)),
  builder: (context, snapshot) {
    if (snapshot.connectionState == ConnectionState.waiting) {
      return Center(child: CircularProgressIndicator());
    } else if (snapshot.hasError) {
      return Center(child: Text('Ошибка: ${snapshot.error}'));
    } else {
      return ListView.builder(
        itemCount: snapshot.data!.length,
        itemBuilder: (context, index) => ListTile(title: Text(snapshot.data![index]['title'])),
      );
    }
  },
)

Экспертные промты: нативные модули и оптимизация

7. Вызов нативного кода на Swift/Kotlin

Задача: Получить версию ОС через платформенный канал.

Промт:

Напиши MethodChannel для получения версии ОС. На стороне Flutter вызови метод getOSVersion. На iOS реализуй на Swift, на Android — на Kotlin. Верни строку.

Пример результата (Flutter):

static const platform = MethodChannel('app.version');
Future<String> getOSVersion() async {
  final String version = await platform.invokeMethod('getOSVersion');
  return version;
}

iOS (Swift):

let controller = window?.rootViewController as! FlutterViewController
let channel = FlutterMethodChannel(name: "app.version", binaryMessenger: controller.binaryMessenger)
channel.setMethodCallHandler { (call, result) in
  if call.method == "getOSVersion" {
    result(UIDevice.current.systemVersion)
  }
}

Android (Kotlin):

MethodChannel(flutterEngine.dartExecutor.binaryMessenger, "app.version").setMethodCallHandler { call, result ->
  if (call.method == "getOSVersion") {
    result.success(android.os.Build.VERSION.RELEASE)
  }
}

8. Оптимизация производительности списка

Задача: Улучшить рендеринг длинного списка с изображениями.

Промт:

У меня есть ListView с 1000 элементов, каждый содержит изображение из сети. Он тормозит. Предложи оптимизацию: используй кеширование изображений и ListView.builder. Напиши улучшенный код.

Пример результата:

CachedNetworkImage(
  imageUrl: item.imageUrl,
  placeholder: (context, url) => CircularProgressIndicator(),
  errorWidget: (context, url, error) => Icon(Icons.error),
)

(Используется пакет cached_network_image)

9. Работа с разрешениями (permissions)

Задача: Запросить разрешение на камеру на обеих платформах.

Промт:

Напиши код для запроса разрешения на камеру в Flutter с использованием пакета permission_handler. Учти различия: на iOS нужно добавить NSCameraUsageDescription в Info.plist, на Android — в AndroidManifest.xml. Покажи пример запроса и обработки отказа.

Пример результата:

final status = await Permission.camera.request();
if (status.isGranted) {
  // открыть камеру
} else if (status.isDenied) {
  showDialog(...);
}

10. Сборка релиза с Flutter build

Задача: Настроить сборку для iOS и Android с разными иконками и названиями.

Промт:

Покажи, как настроить flutter_launcher_icons и flutter_native_splash для генерации иконок и сплэш-скринов под iOS и Android. Напиши конфигурацию в pubspec.yaml.

Пример результата:

flutter_icons:
  android: true
  ios: true
  image_path: "assets/icon.png"

11. Интеграция с React Native: навигация с React Navigation

Задача: Создать стек-навигацию в React Native.

Промт:

Ты — React Native разработчик. Сгенерируй код для StackNavigator с двумя экранами: Home и Details. Используй @react-navigation/native и @react-navigation/stack. Передай параметр с Home на Details.

Пример результата:

import { NavigationContainer } from '@react-navigation/native';
import { createStackNavigator } from '@react-navigation/stack';

const Stack = createStackNavigator();

function App() {
  return (
    <NavigationContainer>
      <Stack.Navigator>
        <Stack.Screen name="Home" component={HomeScreen} />
        <Stack.Screen name="Details" component={DetailsScreen} />
      </Stack.Navigator>
    </NavigationContainer>
  );
}

// HomeScreen: navigation.navigate('Details', { itemId: 42 })
// DetailsScreen: const { itemId } = route.params;

12. Отладка нативных ошибок

Задача: Понять, почему падает приложение на Android при вызове нативного модуля.

Промт:

Моё React Native приложение крашится на Android с ошибкой "Native module cannot be null". Как исправить? Объясни причину и дай пошаговое решение.

Пример результата:
Ошибка возникает, когда модуль не зарегистрирован в MainApplication.java. Нужно добавить пакет в список packages. Пример кода:

@Override
protected List<ReactPackage> getPackages() {
  return Arrays.<ReactPackage>asList(
    new MainReactPackage(),
    new MyCustomPackage() // добавить сюда
  );
}

Заключение

Эти 12 промтов покрывают ключевые этапы разработки кроссплатформенного приложения: от генерации UI до работы с нативными модулями. Они не заменят понимания фреймворков, но значительно ускорят рутину. Помните: AI-ассистент — это инструмент, который усиливает ваши навыки, а не заменяет их. Начните с базовых промтов, постепенно переходите к экспертным. И тогда MVP на двух платформах за выходные перестанет быть фантастикой.

Попробуйте применить хотя бы три промта из этой подборки в своём следующем проекте — и сравните время сборки. Делитесь результатами в комментариях.


Источники:
- Официальная документация Flutter: https://flutter.dev/docs
- Официальная документация React Native: https://reactnative.dev/docs
- Stack Overflow Developer Survey 2025: https://survey.stackoverflow.co/2025/

← Все статьи

Комментарии

Читайте также

Английский язык с AI: как нейросети меняют изучение языка в 2026 году и почему я выбрал этот курс

13 сентября 2026

Промты для Rust и Go: как в одиночку тянуть высоконагруженный бэкенд, пока команда из трёх разработчиков тонет в созвонах

13 сентября 2026

Data Science для бизнеса: как освоить A/B-тестирование, продуктовые метрики и оптимизацию конверсии в 2026 году

13 сентября 2026

Создание MCP-серверов: как подключить ИИ-агентов к реальным API — и почему этот навык востребован

13 сентября 2026

Промпт-инъекции и защита LLM: как курс «Промпт-инжиниринг ПРО (Prompt Engineering Pro)» учит строить безопасные AI-приложения

13 сентября 2026

RAG-системы с нуля: обзор курса и прогнозы развития технологии до 2027 года

13 сентября 2026

System Design Interview: как подготовиться к FAANG в 2026 году и какие тренды учитывать

12 сентября 2026

Flutter и React Native в 2026: 12 промтов, которые реально экономят часы разработки

12 сентября 2026

Промты для Python-разработчика: 10 сценариев LeetCode и Computer Science на техническом собеседовании 2026

12 сентября 2026