Баннер мобильный (3) Пройти тест

Что такое Flutter или как создать простое мобильное приложение

Кроссплатформенная разработка для начинающих

Инструменты

18 октября 2024

Поделиться

Скопировано
Что такое Flutter или как создать простое мобильное приложение

Содержание

    В этой статье мы познакомимся с Flutter — популярным фреймворком для кроссплатформенной разработки. Мы шаг за шагом пройдем через установку инструментов в Visual Studio Code, создадим простое мобильное приложение и запустим его как на эмуляторе, так и на реальном устройстве.

    Что такое Flutter и Dart

    Flutter — популярный фреймворк для кроссплатформенной разработки. С его помощью можно создавать приложения для компьютеров, мобильных устройств и веба. Основной язык программирования для Flutter — Dart.

    Dart — это альтернатива JavaScript. Разработчики хотели сделать язык гибким, структурированным и простым для изучения. Им это удалось.

    Теперь перейдем к практике и начнем с установки инструментов. 

    Как установить плагин Flutter

    Android Studio является официальной IDE (интегрированной средой разработки) от Google. В ней есть возможность установить специальный плагин для разработки на Flutter. Но, видимо, не для России. При попытке установки плагина вы можете столкнуться с таким сообщением:

    Плагин для разработки на Flutter
    Источник: автор статьи

    Перевод: 

    Плагин Flutter не был установлен: к сожалению, в настоящее время мы не можем предоставить вам нашу продукцию или услуги из-за правил экспортного контроля.

    Конечно, можно решить эту проблему через специальные сервисы, но мы не будем этого делать,  а попробуем установить редактор Visual Studio Code и уже через его менеджер расширений поставить все необходимое.

    Visual Studio Code — это мощнейший редактор кода от Microsoft, который при помощи различных расширений можно легко превратить в практически полноценную IDE. Скачать его можно здесь. После установки редактора запускаем его и заходим в раздел расширений. В строке поиска вводим слово flutter и выбираем расширение под названием Flutter от разработчика Dart Code. Нажимаем на кнопку установки. Вместе с этим расширением автоматически установится расширение Dart от того же разработчика.

    Дополнительно можно еще русифицировать редактор. Для этого нам понадобится расширение Russian Language Pack for Visual Studio Code от Microsoft. Находим его и устанавливаем. В общем, наш редактор после всех манипуляций должен выглядеть примерно так:

    Расширение Russian Language Pack for Visual Studio Code
    Источник: автор статьи

    Теперь попробуем создать наш первый проект на Flutter.

    Как написать простое приложение-счетчик на Flutter

    Для создания приложения нужно перейти в меню «Вид» и выбрать там пункт «Палитра команд». В строке поиска пишем flutter и выбираем пункт Flutter: New Project. Далее выбираем в качестве типа проекта Application и выбираем его место расположения. Остается только ввести название проекта (counter) и нажать на клавишу Enter. У нас должно получиться примерно вот это:

    Новый проект
    Источник: автор статьи

    Шаблон проекта успешно создан. Но это еще не все. В правом нижнем углу должно появиться уведомление о том, что не найден Flutter SDK. Это набор инструментов разработки, который необходим для сборки и запуска проекта. Через это же уведомление можно загрузить SDK или если он уже загружен, то указать место его расположения. Загрузить SDK можно отсюда.

    Для запуска приложения нам понадобится эмулятор устройства на Android. Такой эмулятор входит в состав Android SDK. Можно установить Android Studio и вместе с ней установятся все необходимые компоненты. Скачать ее можно здесь

    Для проверки правильности установки всех компонентов воспользуемся инструментом под названием Flutter Doctor. Найдем его в палитре команд и запустим. Вывод его будет примерно таким:

    Flutter Doctor.
    Источник: автор статьи

    Если доктор показывает какие-то проблемы, то скорее всего не хватает каких-то компонентов или их не удалось найти. В таком случае нужно внимательно прочитать вывод доктора и доустановить необходимые компоненты или указать их местоположение в файловой системе.

    Чтобы запустить приложение в эмуляторе, сначала нужно запустить сам эмулятор. Для этого нам снова понадобится палитра команд. Найдем в ней команду Flutter: Launch Emulator и запустим ее. Далее нам будет предоставлен список доступных эмуляторов. Если список пустой, то придется создать эмулятор с помощью Android Studio. Запускаем студию:

    Android Studio
    Источник: автор статьи

    Нажимаем на More Actions и выбираем Virtual Device Manager. Откроется такое окно:

    Virtual Device Manager
    Источник: автор статьи

    Чтобы создать новый эмулятор просто нажимаем на значок плюса и выбираем любой понравившийся телефон или планшет. У нас в списке один уже есть. Итак, если в списке палитры команд отображается хотя бы один эмулятор, то выбираем его и дожидаемся его запуска. Вот эмулятор в запущенном виде:

    Эмулятор
    Источник: автор статьи

    Чтобы запустить проект нажмем на кнопку запуска, расположенную в правой верхней части редактора, прямо над обзорной картой. После успешной сборки приложение запустится в эмуляторе:

    Шаг 1
    Источник: автор статьи

    Нажмем на кнопку со знаком плюс несколько раз, чтобы проверить работу приложения:

    Шаг 2
    Источник: автор статьи

    Все работает! Теперь давайте немного доработаем приложение.

    Доработка приложения

    В шаблоне содержится какой-то урезанный проект. И в самом деле: при нажатии на плюс число будет постоянно увеличиваться. Давайте добавим еще одну кнопку, которая будет уменьшать число. Но сначала изучим исходник поподробнее:

    import 'package:flutter/material.dart';
    
    void main() {
      runApp(const MyApp());
    }
    
    class MyApp extends StatelessWidget {
      const MyApp({super.key});
    
      // This widget is the root of your application.
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          title: 'Flutter Demo',
          theme: ThemeData(
            colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
            useMaterial3: true,
          ),
          home: const MyHomePage(title: 'Flutter Demo Home Page'),
        );
      }
    }
    
    class MyHomePage extends StatefulWidget {
      const MyHomePage({super.key, required this.title});
      final String title;
    
      @override
      State<MyHomePage> createState() => _MyHomePageState();
    }
    
    class _MyHomePageState extends State<MyHomePage> {
      int _counter = 0;
    
      void _incrementCounter() {
        setState(() {
          _counter++;
        });
      }
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(
            backgroundColor: Theme.of(context).colorScheme.inversePrimary,
            title: Text(widget.title),
          ),
          body: Center(
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: <Widget>[
                const Text(
                  'You have pushed the button this many times:',
                ),
                Text(
                  '$_counter',
                  style: Theme.of(context).textTheme.headlineMedium,
                ),
              ],
            ),
          ),
          floatingActionButton: FloatingActionButton(
            onPressed: _incrementCounter,
            tooltip: 'Increment',
            child: const Icon(Icons.add),
          ), // This trailing comma makes auto-formatting nicer for build methods.
        );
      }
    }

    Что мы здесь видим? В самом начале исходника импортируется пакет material.dart. Из названия должно быть понятно, что он нужен для создания дизайна приложения в стиле Material Design. Далее идет точка входа в приложение — метод main. В его теле содержится вызов одного единственного метода runApp. На вход этого метода подается класс MyApp. В этом классе происходит установка заголовков, тем и домашней страницы. Дальше следует, собственно, сам класс домашней страницы MyHomePage, а за ним класс _MyHomePageState, в котором содержатся описание интерфейса и логика приложения.

    Кнопка floatingActionButton (плавающая кнопка) описывается в самом конце класса _MyHomePageState. При нажатии на кнопку срабатывает метод _incrementCounter, который увеличивает число в компоненте Text на единицу. Нам нужно добавить еще одну кнопку, навесив на нее метод _decrementCounter, который будет уменьшать число на единицу.

    Кнопки можно разместить в контейнере Row. Он расположит их горизонтально. Таким образом код для кнопок будет выглядеть так:

    Row(
      mainAxisAlignment: MainAxisAlignment.spaceAround,
      children: [
       FloatingActionButton(
        onPressed: _decrementCounter,
        tooltip: 'Decrement',
        child: const Icon(Icons.remove),
       ),
       FloatingActionButton(
        onPressed: _incrementCounter,
        tooltip: 'Increment',
        child: const Icon(Icons.add),
       ),
      ],
    )

    Метод _decrementCounter:

    void _decrementCounter() {
        setState(() {
          _counter--;
        });
      }

    Соответственно, весь код получится такой:

    import 'package:flutter/material.dart';
    
    void main() {
      runApp(const MyApp());
    }
    
    class MyApp extends StatelessWidget {
      const MyApp({super.key});
    
      // This widget is the root of your application.
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          title: 'Flutter Demo',
          theme: ThemeData(
            colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
            useMaterial3: true,
          ),
          home: const MyHomePage(title: 'Flutter Demo Home Page'),
        );
      }
    }
    
    class MyHomePage extends StatefulWidget {
      const MyHomePage({super.key, required this.title});
      final String title;
    
      @override
      State<MyHomePage> createState() => _MyHomePageState();
    }
    
    class _MyHomePageState extends State<MyHomePage> {
      int _counter = 0;
    
      void _incrementCounter() {
        setState(() {
          _counter++;
        });
      }
    
      void _decrementCounter() {
        setState(() {
          _counter--;
        });
      }
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(
            backgroundColor: Theme.of(context).colorScheme.inversePrimary,
            title: Text(widget.title),
          ),
          body: Center(
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: <Widget>[
                const Text(
                  'You have pushed the button this many times:',
                ),
                Text(
                  '$_counter',
                  style: Theme.of(context).textTheme.headlineMedium,
                ),
                Row(
                  mainAxisAlignment: MainAxisAlignment.spaceAround,
                  children: [
                    FloatingActionButton(
                      onPressed: _decrementCounter,
                      tooltip: 'Decrement',
                      child: const Icon(Icons.remove),
                    ),
                    FloatingActionButton(
                      onPressed: _incrementCounter,
                      tooltip: 'Increment',
                      child: const Icon(Icons.add),
                    ),
                  ],
                )
              ],
            ),
          ),
        );
      }
    }

    Контейнер Row с кнопками мы расположили сразу после компонента Text. И теперь интерфейс приложения должен выглядеть более компактно, так как все компоненты собрались в центральной области экрана. Теперь попробуем запустить наше приложение в эмуляторе. Выглядеть оно будет следующим образом:

    Шаг 3
    Источник: автор статьи
    Шаг 4
    Источник: автор статьи
    Шаг 5
    Источник: автор статьи

    Вот теперь это похоже на Counter. Далее поговорим о том, как запустить наше приложение на физическом девайсе.

    Как запустить приложение на Flutter на смартфоне

    Для запуска нашего приложения на физическом смартфоне сначала необходимо активировать на нем режим разработчика. Мы будем использовать старенький Samsung Galaxy A6. В разделе сведений о ПО (в настройках) находим пункт «Номер сборки» и тапаем по нему несколько раз. После появления уведомления о том, что режим разработчика активирован, возвращаемся в список настроек и видим, что там появился новый пункт под названием «Параметры разработчика»:

    Шаг 6
    Источник: автор статьи

    Заходим в него и ищем пункт «Отладка по USB». Активируем этот пункт:

    Шаг 7
    Источник: автор статьи

     Далее подключаем телефон к компьютеру. Разрешаем передачу данных и отладку по USB в появившихся диалоговых окнах. Наконец, запускаем Visual Studio Code с нашим проектом. В боковой панели заходим во вкладку Flutter и видим там наш девайс (SM A600FN):

    Шаг 8
    Источник: автор статьи

    Нажимаем на кнопку запуска и через некоторое время видим наше приложение запущенное на телефоне:

    Шаг 9
    Источник: автор статьи
    Шаг 10
    Источник: автор статьи
    Шаг 11
    Источник: автор статьи

    А сейчас предлагаем выполнить небольшое задание.

    Задание для самостоятельного выполнения

    Добавьте в интерфейс приложения еще одну кнопку для сброса значений счетчика. Расположите ее между двумя имеющимися. Также поменяйте надпись в заголовке страницы на «Counter».

    Решение

    Код для контейнера с добавленной кнопкой сброса:

    Row(
      mainAxisAlignment: MainAxisAlignment.spaceAround,
      children: [
       FloatingActionButton(
        onPressed: _decrementCounter,
        tooltip: 'Decrement',
        child: const Icon(Icons.remove),
       ),
       FloatingActionButton(
        onPressed: _resetCounter,
        tooltip: 'Reset',
        child: const Icon(Icons.restart_alt),
       ),
       FloatingActionButton(
        onPressed: _incrementCounter,
        tooltip: 'Increment',
        child: const Icon(Icons.add),
       ),
      ],
    )

    Метод _resetCounter:

    void _resetCounter() {
        setState(() {
          _counter = 0;
        });
      }

    Заголовок меняем в возврате MaterialApp, что прописан в классе MyApp:

    home: const MyHomePage(title: 'Counter')

    Весь код будет такой:

    import 'package:flutter/material.dart';
    
    void main() {
      runApp(const MyApp());
    }
    
    class MyApp extends StatelessWidget {
      const MyApp({super.key});
    
      // This widget is the root of your application.
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          title: 'Flutter Demo',
          theme: ThemeData(
            colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
            useMaterial3: true,
          ),
          home: const MyHomePage(title: 'Counter'),
        );
      }
    }
    
    class MyHomePage extends StatefulWidget {
      const MyHomePage({super.key, required this.title});
      final String title;
    
      @override
      State<MyHomePage> createState() => _MyHomePageState();
    }
    
    class _MyHomePageState extends State<MyHomePage> {
      int _counter = 0;
    
      void _incrementCounter() {
        setState(() {
          _counter++;
        });
      }
    
      void _resetCounter() {
        setState(() {
          _counter = 0;
        });
      }
    
      void _decrementCounter() {
        setState(() {
          _counter--;
        });
      }
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(
            backgroundColor: Theme.of(context).colorScheme.inversePrimary,
            title: Text(widget.title),
          ),
          body: Center(
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: <Widget>[
                const Text(
                  'You have pushed the button this many times:',
                ),
                Text(
                  '$_counter',
                  style: Theme.of(context).textTheme.headlineMedium,
                ),
                Row(
                  mainAxisAlignment: MainAxisAlignment.spaceAround,
                  children: [
                    FloatingActionButton(
                      onPressed: _decrementCounter,
                      tooltip: 'Decrement',
                      child: const Icon(Icons.remove),
                    ),
                    FloatingActionButton(
                      onPressed: _resetCounter,
                      tooltip: 'Reset',
                      child: const Icon(Icons.restart_alt),
                    ),
                    FloatingActionButton(
                      onPressed: _incrementCounter,
                      tooltip: 'Increment',
                      child: const Icon(Icons.add),
                    ),
                  ],
                )
              ],
            ),
          ),
        );
      }
    }

    Запущенное приложение:

    Шаг 12
    Источник: автор статьи

    Инструменты

    Поделиться

    Скопировано
    0 комментариев
    Комментарии