Как создать приложение с прайс-листом криптовалюты с помощью Flutter SDK

1656664944 kak sozdat prilozhenie s prajs listom kriptovalyuty s pomoshhyu flutter sdk

Flutter – новинка Google открытый источник набор инструментов, который помогает разработчикам создавать приложения для iOS и Android только с помощью одна кодовая база. Программы Flutter написаны на языке программирования Dart и компилируются родной кода, поэтому производительность действительно великолепна.

В этом учебнике я покажу вам, как использовать Flutter для создания приложения, показывающего текущую цену различных криптовалют. Я расскажу вам об основах Flutter и Dart.

Прежде чем начать, установите Flutter и плагин редактора Flutter, если вы этого еще не сделали. Установка должна быть простой, но если вы столкнетесь с проблемами, вы можете оставить комментарий к этой публикации, и я буду рад помочь.

Для этого учебника я буду использовать Android Studio, но вы также можете использовать IntelliJ или Visual Studio Code.

Также требуется определенный опыт объектно-ориентированного программирования (ООП). Расслабься! Вам не нужен многолетний опыт – если вы знаете, что такое классы и объекты, у вас все хорошо.

Давайте начнем

В Android Studio или IntelliJ нажмите Файл меню -> новый -> Новый Флаттер Ппроект. Если вы не видитеe the New Flutter Project, убедитесь, что вы установили плагин Flutter. Если вы используете Visual Studio Code, выполните следующие действия, чтобы создать новый проект.

1*oE6SlcmuRJwR-tHRJzpZvA

Когда откроется страница, выберите Приложение Flutter и нажмите на Дальше кнопку.

1*SM_ttARLHyGXP38TaxMngA

На следующей странице можно настроить проект. Вы можете использовать подобную конфигурацию, как на рисунке ниже. Просто убедитесь, что путь Flutter SDK указывает на каталог, куда вы загрузили Flutter.

1*uEgNPColbpe8DQTqc5EE5g

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

Создание проекта должно начаться по нажатию кнопки завершения, которая обычно занимает несколько минут.

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

1*SOKlN4-dxCw4X-CAN1_ZAA

Вызываемый файл main.dart была создана в lib папку. Он содержит код демонстрационной программы. Поскольку мы будем создавать нашу программу с нуля, откройте main.dart файл и удалите/очистите весь код в нем.

Если ваш проект включает a test каталог, содержащий файл widget_test.dart, удалите этот файл перед продолжением. Он содержит тесты для кода, который мы только что удалили.

Программы Flutter написаны на языке программирования Dart. The main.dart файл является исходным файлом Dart (.dart расширение). Конвенция Dart подразумевает именование исходных файлов с помощью lowercase_with_underscores.

Давайте начнем писать код Dart. Мы начнем с традиции программирования: печать Hello World!

Для этого нам придется создать что-то под названием main функция. The main Функция – это функция верхнего уровня, которая есть в каждой программе Flutter и служит точкой входа в вашу программу. Подумайте об этом как о входе в дом.

1*hC831nn9aLYCdcGaYkDQGw

Когда вы запускаете приложение на устройстве, выполнение начнется с основной функции. Давайте создадим простой main поэтому введите следующий код в свой main.dart файл.

Как видите, создавая main функция проста. Вторая строка содержит main объявление функции: ее тип возврата (void) и имя (main). Основная функция возвращается void то есть ничего не возвращает.

Третья строка выполняет печать на консоль. Мы называем print и передать ей строчный аргумент. Заметьте, что в Dart вы можете использовать одинарные кавычки (‘string’) или двойные кавычки (“string”) при объявлении строчного литерала.

Для запуска кода нажмите зеленую кнопку запуска (воспроизведение) в верхней части Android Studio или IntelliJ. Убедитесь, что реальное устройство подключено или запущен эмулятор.

1*3TYytoIBY2UvLR-VOdR_Cw

После успешного запуска программы вы должны увидеть Hello World! напечатано на консоли.

1*smn4mdtI8SzSkRH0c0I3Ew

Но если вы проверите устройство или эмулятор, вы увидите что-то нелестное.

1*NXFISzRQgevj7BjxiAtIPw
Пустой экран

Что ж, это было ожидаемо, поскольку сейчас мы печатаем только на консоли. К пользовательскому интерфейсу программы ничего не добавлено, поэтому он пуст.

Давайте исправим это, добавив некоторые элементы к пользовательскому интерфейсу программы. Наше приложение будет использовать материальный дизайн, поэтому давайте добавим пакет к main.dart файл, чтобы помочь с этим.

import 'package:flutter/material.dart';

Как и любой современный язык программирования, можно импортировать библиотеку/пакет для использования в своем коде. Здесь мы импортируем material.dart пакет. Этот пакет содержит код, который помогает нам создать программу со стилистикой материала.

The material.dart пакет имеет функцию под названием runApp. The runApp берет виджет и прикрепляет его к экрану. Ну что такое виджет?

1*NK6qwYtoWPzPrUptqheOnQ
Виджеты

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

Flutter уже поставляется с набором мощных виджетов, таких как текст и изображения. The material.dart пакет, который мы только что импортировали, содержит несколько виджетов материального дизайна, которые мы скоро будем использовать.

Давайте использовать runApp сейчас, чтобы показать «Hello World!» в центре экрана устройства. Заменить содержимое main функцию с нижеприведенным кодом.

void main() {
  print('Hello World!');
  
  // Runs the MaterialApp widget
  runApp(new MaterialApp(
    // This is the widget that is displayed first when the application is started normally
    home: new Center(
      // The Text widget is wrapped in a center widget to center it on the screen
      child: new Text('Hello World!'),
    ),
  ));
}

Позвольте мне объяснить некоторые новые вещи в коде выше

  1. new: Чтобы создать объект, вы обычно используете new ключевое слово из a конструктор для класса. (ООП)
  2. new MaterialApp(): здесь мы создаем новый объект виджета под названием MaterialApp. The MaterialApp Виджет создает ряд полезных вещей, необходимых для программы материального дизайна.
  3. home:: в Dart мы можем четко указать название каждого параметра при вызове функции/конструктора. Виджет передан как home Параметр отображается первым, когда приложение запускается нормально.
  4. new Center(child: new Text('Hello World!')) : мы заворачиваем виджет «Текст» в виджет «Центр», чтобы текст был центрирован на экране. Виджет «Текст» является дочерним виджетом «Центр». Да, виджеты могут быть вложенными.
1*Z79-bHQP9bhwSh9IYlaMTA

Если вы снова запустите код и откроете устройство, вы получите немного лучший экран.

1*Gnn1V4u5ClUok_kAeOnl4g

Круто! Нам удалось показать уродливый текст в центре экрана устройства.

Следующие шаги

Давайте сейчас сделаем несколько шагов вперед. Мы будем получать цены на криптовалюту из API CoinMarketCap. API возвращает массив JSON. Вот образец ответа от API:

[
    {
        "name": "Bitcoin", 
        "price_usd": "11525.7", 
        "percent_change_1h": "-0.18",
        ...
    },
    ...
]

Мы отправим запрос в API CoinMarketCap и расшифруем JSON из программы. Нам придется добавить несколько новых пакетов к main.dart файл.

import 'dart:async';
import 'dart:convert';
import 'package:http/http.dart' as http;

Вот обзор новых пакетов:

  1. dart:async: обеспечивает Future класса, о котором я расскажу подробнее ниже.
  2. dart:convert: обеспечивает json переменная, которую мы будем использовать для декодирования строкового ответа JSON.
  3. package:http/http.dart: Предоставляет функцию, которую мы будем использовать для выполнения запросов HTTP GET.

Давайте добавим новую функцию к main.dart файл, посылающий запрос в API CoinMarketCap.


Future<List> getCurrencies() async {
  String apiUrl="
  // Make a HTTP GET request to the CoinMarketCap API.
  // Await basically pauses execution until the get() function returns a Response
  http.Response response = await http.get(apiUrl);
  // Using the JSON class to decode the JSON String
  return JSON.decode(response.body);
}

Давайте пройдемся по новому коду

Future<List> : Мы в основном говорим, что getCurrencies() функция вернет a List когда-то в будущем. Он сделает HTTP-запрос к API CoinMarketCap и вернет a List валют после завершения.

The getCurrencies() функция асинхронная. Если у вас есть определенный опыт работы с JavaScript, вы можете придумать Futures как Promises. Я создал изображение ниже, чтобы помочь вам понять Futures в Dart.

1*YrTpSezcRdjSQl5M6R33IA
Боб вызывает асинхронную функцию askKateForBalloons(), возвращающую Future
1*dyGmD3Z6t0uEFYthWVUq0A
Боб может сохранить будущее
1*fj18OGjh4wfy42q5XXTwWg
Боб может знать, когда завершится Будущее

async and await :

Await Выражения позволяют писать асинхронный код почти так, будь он синхронен. The http.get(url) функция асинхронная, возвращает a Future<Response> немедленно, когда его вызывают. Мы хотим дождатьсяr the Response, чтобы мы могли декодировать строку JSON, но мы также не хотим использовать уродливые обратные вызовы.

The await выражение оценивает http.get(url)а затем приостанавливает текущую запущенную функцию (getCurrencies()), пока результат не будет готов – то есть к завершению будущего.

Использовать await, код должен находиться в функции, обозначенной как асинхронная. Ан async функция — функция, тело которой обозначено знаком async модификатор. Когда вы звоните async она немедленно возвращает Future. Тело функции запланировано для выполнения позже.

Вы можете прочитать больше о async и await в Dart здесь.

http.get(url) : делает HTTP-запрос GET в CoinMarketCap API. Эта функция асинхронна и немедленно возвращает Future.

  1. JSON.decode(response.body) : декодирует строчный ответ JSON.

Давайте проверим getCurrencies() функцию, которую мы только что создали. Мы делаем это, делая вызов к нему в нашем main функцию и печать возвращенного значения на консоль.

// Since we are using await within the main function, we have to make it asynchronous too
void main() async {
  // Testing the getCurrencies function
  // We wait for the currency data to arrive
  List currencies = await getCurrencies();
  // Before printing it to the Console
  print(currencies);
  
  runApp(new MaterialApp(
    home: new Center(
      child: new Text('Hello World!'),
    ),
  ));

Если вы запустите код выше, вы увидите ответ API, напечатанный на консоли.

1*asbOqbSU3_M12wYvbe4vSw

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

В рабочей программе вам предстоит решать сбой сети. Вы делаете это, размещая вызов HTTP в a try…catch блокировать.

Создание пользовательского интерфейса

Теперь, когда у нас есть список валют, давайте создадим пользовательский интерфейс для отображения этого списка.

При написании программ Flutter вы обычно создаете новые классы виджетов. Основная задача виджета состоит в реализации a build функция, описывающая виджет с точки зрения других виджетов более низкого уровня.

Давайте создадим новый виджет под названием CryptoListWidget. Добавьте следующий код внизу своего main.dart файл.

class CryptoListWidget extends StatelessWidget {
  
  // This is a list of material colors. Feel free to add more colors, it won't break the code
  final List<MaterialColor> _colors = [Colors.blue, Colors.indigo, Colors.red];
  // The underscore before a variable name marks it as a private variable
  final List _currencies;

  // This is a constructor in Dart. We are assigning the value passed to the constructor
  // to the _currencies variable
  CryptoListWidget(this._currencies);

  @override
  Widget build(BuildContext context) {
    // Build describes the widget in terms of other, lower-level widgets.
    return new Text('Hello World!');
  }

}

Давайте пройдемся по новому коду выше:

  1. StatelessWidget : обычно вы создаете виджеты, являющиеся подклассами любого StatelessWidget или StatefulWidgetв зависимости от того, управляет ли ваш виджет любым состоянием. Мы используем StatelessWidget потому что у нас уже есть наши данные, и мы не будем обновлять их в этом руководстве.
  2. final List<MaterialColor> _цвета: переменные in a StatelessВиджет Шоуld be окончательные (т.е. они постоянны или не изменяются). Вот мы декларируемing a конечная переменная, содержащая list of MaterialЦветы. Нижниеcore(_) перед тем, как название переменной делает его закрытым (недоступным из других классов).
  3. CryptoListWidget(this._currencies) : Это конструктор для нашего виджета Он назначает список валют, которые мы передаем в конструктор. _currencies переменная.
  4. build функция: метод построения возвращает виджет низшего уровня (Text), описывающий, как это будет выглядеть.

Давайте заменим текстовый виджет в build функция выше с новым виджетом под названием Scaffold. The Scaffold Виджет реализует базовую структуру визуального макета материального дизайна. Замените build функцией выше с тем, что ниже.

@override
  Widget build(BuildContext context) {
    return new Scaffold(
      body: _buildBody(),
      backgroundColor: Colors.blue,
    );
  }

Класс Scaffold предоставляет API для показа ящиков, перемещения кнопки действия, нижней панели, панели закусочных и так далее. Позже мы добавим плавающую кнопку действия.

1*PsoStgOHjRfZ2C2saoPQEw

Вы должны получить предупреждение об этом _buildBody() не определено для класса CryptoListWidget. Давайте дальше творить _buildBody() функция внутри CryptoListWidget класс.

Widget _buildBody() {
    return new Container(
      // A top margin of 56.0. A left and right margin of 8.0. And a bottom margin of 0.0.
      margin: const EdgeInsets.fromLTRB(8.0, 56.0, 8.0, 0.0),
      child: new Column(
        // A column widget can have several widgets that are placed in a top down fashion
        children: <Widget>[
          _getAppTitleWidget(),
          _getListViewWidget()
        ],
      ),
    );
  }

Синтаксис здесь должен быть знаком. Мы используем два новых виджета:

  1. Container виджет: А Container виджет – это просто контейнер 🙂 (для других виджетов).
  2. Виджет столбцов: A Column макеты виджетов список дочерних виджетов в вертикальном направлении. Он имеет параметр под названием children принимающий список виджетов.

Давайте создадим две функции, которые мы вызывали в _buildBody() функция. Первый есть _getAppTitleWidget() .

Widget _getAppTitleWidget() {
    return new Text(
      'Cryptocurrencies',
      style: new TextStyle(
          color: Colors.white,
          fontWeight: FontWeight.bold,
          fontSize: 24.0),
    );
  }

Эта функция возвращает регулярное значение Text виджет со стилем, делающим его жирным и белым с размером шрифта 24,0.

Когда мы запускаем приложение, текст будет выглядеть так.

1*fAbESNYbWMV900x1Fq84CA

Мы еще не можем запустить приложение, поскольку мы не создали другую функцию под названием _getListViewWidget(). Давайте быстро создадим его с помощью приведенного ниже кода.

Widget _getListViewWidget() {
    // We want the ListView to have the flexibility to expand to fill the
    // available space in the vertical axis
    return new Flexible(
        child: new ListView.builder(
            // The number of items to show
            itemCount: _currencies.length,
            // Callback that should return ListView children
            // The index parameter = 0...(itemCount-1)
            itemBuilder: (context, index) {
              // Get the currency at this position
              final Map currency = _currencies[index];

              // Get the icon color. Since x mod y, will always be less than y,
              // this will be within bounds
              final MaterialColor color = _colors[index % _colors.length];

              return _getListItemWidget(currency, color);
            }));
  }

The _getListViewWidget() возвращает a ListView виджет, завернутый в a Flexible виджет. Мы используем ListView.builder чтобы легко создать список. Проходим в ан itemCount который уведомляет строителя, сколько валют показать.

The itemBuilder обратный вызов будет вызван для каждого элемента, и вы должны вернуть новый виджет. В приведенном выше коде мы вызываем функцию под названием _getListItemWidget() возвращающий виджет.

CircleAvatar _getLeadingWidget(String currencyName, MaterialColor color) {
    return new CircleAvatar(
      backgroundColor: color,
      child: new Text(currencyName[0]),
    );
  }

Прежде чем мы создадим _getListItemWidget() давайте быстро создадим отдельные элементы для виджета ListView. Мы хотим, чтобы каждый элемент в ListView выглядел так:

1*O3HD57q2Ovl5MPUyndgWUw

Итак, у нас есть три основных виджета:

  1. Виджет круглый значок с первым символом названия валюты.
  2. Текстовый виджет с названием валюты
  3. Текстовый виджет с изменением цены и процента за 1 час.
Text _getTitleWidget(String currencyName) {
    return new Text(
      currencyName,
      style: new TextStyle(fontWeight: FontWeight.bold),
    );
  }

  Text _getSubtitleWidget(String priceUsd, String percentChange1h) {
    return new Text('\$$priceUsd\n1 hour: $percentChange1h%');
  }

Давайте создадим виджеты. Для простоты я создал функцию для каждого из них. Первая вызванная функция _getLeadingWidget() возвращает круглый значок с текстом.

Виджет будет выглядеть так:

1*QkD7n2hBzTXCL5yiANx2Xg

Вторая функция вызвана _getTitleWidget возвращает Text виджет для наименования валюты.

Третья функция под названием _getSubtitleWidget() возвращает Text виджет текущей цены валюты и изменения процентов за 1 час.

Оба эти виджета должны выглядеть так:

1*hIF928PlzKa_tOi3CPE0mg

Давайте завернем все три виджета во что-то под названием a ListTile виджет. The ListTile виджет основан на документации Material Design List. Он показывает все три виджета в этом стиле.

1*O3HD57q2Ovl5MPUyndgWUw

Мы создадим новую функцию под названием _getListTile что возвращает a ListTile виджет.

ListTile _getListTile(Map currency, MaterialColor color) {
    return new ListTile(
      leading: _getLeadingWidget(currency['name'], color),
      title: _getTitleWidget(currency['name']),
      subtitle: _getSubtitleWidget(
          currency['price_usd'], currency['percent_change_1h']),
      isThreeLine: true,
    );
  }

Наконец, давайте создадим _getListItemWidget() . Он собирается вернуться a Container виджет с верхним отступом 5.0 и a Card дочерний виджет. Виджет карты имеет ListTile возвращено _getListTile как ребенок.

Container _getListItemWidget(Map currency, MaterialColor color) {
    // Returns a container widget that has a card child and a top margin of 5.0
    return new Container(
      margin: const EdgeInsets.only(top: 5.0),
      child: new Card(
        child: _getListTile(currency, color),
      ),
    );
  }

Виджет будет выглядеть так.

1*SFq5wfAj25va2RZkaWX3Kg

Мы успешно завершили нашу CryptoListWidget. Но мы должны обновить main чтобы отобразить только что созданный виджет вместо Text виджет.

void main() async {
  // Bad practice alert :). You should ideally show the UI, and probably a progress view,
  // then when the requests completes, update the UI to show the data.
  List currencies = await getCurrencies();
  print(currencies);
  
  runApp(new MaterialApp(
    home: new CryptoListWidget(currencies),
  ));
}

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

1*5UqjvSl_Q9SEJESOoXSJHw

В самом деле круто, правда?

Приложение, которое вы видите, будет несколько отличаться от снимка экрана выше:

  1. Он не имеет плавающей кнопки действия внизу справа.
  2. Цвет текста изменения за 1 час черный.

Я решил не включать в учебник. Но вы можете проверить репозиторий проекта Github, чтобы узнать, как я смог этого добиться.

Готовое приложение можно скачать здесь.

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

Добавить комментарий

Ваш адрес email не будет опубликован.