Skip to content

Latest commit

 

History

History
909 lines (652 loc) · 60.5 KB

README.ru.md

File metadata and controls

909 lines (652 loc) · 60.5 KB

Языки: Русский (этот файл), индонезийский, урду, Английский, Китайский, Бразильский Португальский, Испанский, Польский, Kорейский, French.

pub package building style: effective dart Discord Shield Get on Slack Telegram Awesome Flutter Buy Me A Coffee

Про Get

  • GetX - это сверхлегкое и мощное решение для Flutter. Оно совмещает в себе высокопроизводительное управление состоянием, интеллектуальное внедрение зависимостей, управление маршрутами быстрым и практичным способом.

  • GetX имеет 3 базовых принципа, являющихся приоритетом для всех ресурсов в библиотеке

    • Производительность: GetX сфокусирован на производительности и минимальном потреблении ресурсов. Бенчмарки почти всегда не имеют значения в реальном мире, но, если Вам угодно, здесь (бенчмарки) есть индикаторы потребления, где GetX работает лучше, чем другие подходы к управлению состоянием. Разница небольшая, но демонстрирует нашу заботу о ресурсах.
    • Продуктивность: GetX использует простой и приятный синтаксис. Не имеет значения, что вы хотите сделать, всегда есть более легкий способ с GetX. Это сэкономит часы разработки и обеспечит максимальную производительность, которую может обеспечить ваше приложение.
    • Организация: GetX позволяет полностью разделить представление, логику представления, бизнес-логику, внедрение зависимостей и навигацию. Вам не нужен контекст для навигации между маршрутами, поэтому вы не зависите от дерева виджетов. Вам не нужен контекст для доступа к вашим контроллерам / блокам через наследуемый виджет, поэтому вы полностью отделяете логику представления и бизнес-логику от уровня визуализации. Вам не нужно внедрять классы Controllers / Models / Blocs в дерево виджетов через мультипровайдеры, поскольку GetX использует собственную функцию внедрения зависимостей, полностью отделяя DI от его представления. С GetX вы знаете, где найти каждую функцию вашего приложения, имея чистый код по умолчанию. Это, помимо упрощения обслуживания, делает возможным совместное использование модулей, что до того момента во Flutter было немыслимо. BLoC был отправной точкой для организации кода во Flutter, он отделяет бизнес-логику от визуализации. Getx является естественным развитием этого, разделяя не только бизнес-логику, но и логику представления. Дополнительное внедрение зависимостей и маршрутов также разделено, и уровень данных не учитывается. Вы знаете, где все находится, и это проще, чем написать "Hello World". GetX - это самый простой, практичный и масштабируемый способ создания высокопроизводительных приложений с помощью Flutter SDK с большой экосистемой вокруг него, которая отлично работает, прост для новичков и точен для экспертов. Он безопасен, стабилен, актуален и предлагает огромный набор встроенных API, которых нет в Flutter SDK по умолчанию.
  • GetX не раздут. Он имеет множество функций, которые позволяют вам начать программировать, ни о чем не беспокоясь, но каждая из этих функций находится в отдельных контейнерах и запускается только после использования. Если вы используете только управление состоянием, то будет скомпилировано только управление состоянием. Если вы используете маршрутизацию, то ничего из управления состоянием не будет скомпилировано. Вы можете воспользоваться репозиторием бенчмарка, и вы увидите, что используя только управление состоянием Get, приложение, которое скомпилировано с помощью Get, имеет меньший размер, чем приложения использующие другие пакеты для управления состоянием, потому что всё, что не используется, не будет скомпилировано в Ваш код. Таким образом каждое решение GetX было спроектировано, чтобы быть сверхлёгким. Также в этом есть и заслуга Flutter, который умеет устранять неиспользуемые ресурсы, как ни один другой фреймворк.

  • Getx имеет огромную экосистему, способную работать с одним и тем же кодом на Android, iOS, в Интернете, Mac, Linux, Windows и на вашем сервере. С помощью Get Server ваш код, созданный на веб-интерфейсе, можно повторно использовать на вашем сервере.

Кроме того, весь процесс разработки может быть полностью автоматизирован как на сервере, так и во внешнем интерфейсе с помощью Get CLI.

Кроме того, для дальнейшего повышения вашей продуктивности у нас есть расширение для VSCode и расширение для Android Studio / Intellij.

Установка

Добавьте Get в файл pubspec.yaml:

dependencies:
  get:

Импортируйте Get в файлы, в которых планируете его использовать:

import 'package:get/get.dart';

Приложение "Счётчик" с GetX

Проект "Счётчик", созданный по умолчанию для нового проекта на Flutter, имеет более 100 строк (с комментариями). Чтобы показать возможности Get, я продемонстрирую, как сделать "Счётчик", изменяющий состояние при каждом клике, переключении между страницами и передаче состояния между экранами. Всё это вместе с разделением бизнес логики от представления занимает ВСЕГО ЛИШЬ 26 СТРОК КОДА, ВКЛЮЧАЯ КОММЕНТАРИИ.

  • Шаг 1: Добавьте "Get" перед вашим MaterialApp, превращая его в GetMaterialApp
void main() => runApp(GetMaterialApp(home: Home()));
  • Примечание: это не изменяет MaterialApp, GetMaterialApp не является модифицированным MaterialApp, это просто предварительно настроенный виджет, у которого в качестве дочернего по умолчанию используется MaterialApp. Вы можете настроить это вручную, но это не обязательно. GetMaterialApp будет создавать маршруты, вводить их, вводить переводы, вводить всё, что вам нужно для навигации. Если вы используете Get только для управления состоянием или зависимостями, нет необходимости использовать GetMaterialApp. GetMaterialApp необходим для навигации, снекбаров, интернационализации, bottomSheets, диалогов и API, связанных с маршрутами и отсутствием контекста.

  • Примечание²: Этот шаг необходим только в том случае, если вы собираетесь использовать управление маршрутами (Get.to(), Get.back() и так далее). Если вы не собираетесь его использовать, то шаг 1 выполнять необязательно.

  • Шаг 2: Создайте свой класс бизнес-логики и поместите в него все переменные, методы и контроллеры. Вы можете сделать любую переменную наблюдаемой, используя простой ".obs".

class Controller extends GetxController{
  var count = 0.obs;
  increment() => count++;
}
  • Шаг 3: Создайте свой View, используйте StatelessWidget и сэкономьте немного оперативной памяти, с Get вам больше не нужно использовать StatefulWidget.
class Home extends StatelessWidget {

  @override
  Widget build(context) {
    
    // Создайте экземпляр вашего класса с помощью Get.put(), чтобы сделать его доступным для всех "дочерних" маршрутов.
    final Controller c = Get.put(Controller());

    return Scaffold(
      // Используйте Obx(()=> чтобы обновить Text() как только count изменится.
      appBar: AppBar(title: Obx(() => Text("Кликов: ${c.count}"))),

      // Замените 8 строк Navigator.push простым Get.to(). Вам не нужен context!
      body: Center(child: ElevatedButton(
              child: Text("Перейти к Other"), onPressed: () => Get.to(Other()))),
      floatingActionButton:
          FloatingActionButton(child: Icon(Icons.add), onPressed: c.increment));
  }
}

class Other extends StatelessWidget {
  // "Попросите" Get найти и предоставить вам ваш Controller, используемый на другой странице.
  final Controller c = Get.find();

  @override
  Widget build(context){
     // Получите доступ к обновленной переменной count
     return Scaffold(body: Center(child: Text("${c.count}")));
  }
}

Результат:

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

Get был разработан для работы с командами, но он упрощает работу отдельного разработчика.

Оптимизируйте ваши сроки, доставляйте всё вовремя без потери производительности. Get не для всех, но, если вы идентифицировали себя с предыщим предложением, Get для вас!

Три столпа

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

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

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

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

Get имеет два разных менеджера состояний: простой менеджер состояний (мы назовем его GetBuilder) и реактивный менеджер состояний (который называется GetX).

Реактивное управление состоянием

Реактивное программирование может оттолкнуть многих людей, потому что считается сложным. GetX превращает реактивное программирование в нечто довольно простое:

  • Вам не нужно создавать StreamControllers.
  • Вам не нужно создавать StreamBuilder для каждой переменной.
  • Вам не нужно создавать класс для каждого состояния.
  • Вам не нужно создавать геттер начального значения.

Реактивное программирование с Get так же просто, как использование setState.

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

Это ваша переменная:

var name = 'Джонатас Борхес';

Чтобы сделать его наблюдаемым, вам просто нужно добавить в конец ".obs":

var name = 'Джонатас Борхес'.obs;

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

Obx(() => Text("${controller.name}"));

Вот и всё. Это так просто.

Подробнее об управлении состоянием

Более подробное объяснение управления состоянием здесь. Там вы увидите больше примеров, а также разницу между простым менеджером состояния и реактивным менеджером состояния.

Вы получите хорошее представление о мощности GetX.

Управление маршрутами

Если вы собираетесь использовать маршруты / снекбары / диалоги / bottomsheets без контекста, GetX отлично подойдёт вам, просто посмотрите:

Добавьте "Get" перед MaterialApp, превратив его в GetMaterialApp.

GetMaterialApp( // Ранее: MaterialApp(
  home: MyHome(),
)

Перейдите на новый экран:

Get.to(NextScreen());

Перейдите на новый экран с именем. Более подробную информацию об именованных маршрутах смотрите здесь

Get.toNamed('/details');

Закрыть снекбар, диалог, bottomsheets, или что-то иное, что вы обычно закрывали с помощью Navigator.pop(context);

Get.back();

Для перехода к следующему экрану без возможности вернуться к предыдущему экрану (для использования в SplashScreens, экранах входа и т. д.)

Get.off(NextScreen());

Для перехода к следующему экрану и отмены всех предыдущих маршрутов (полезно в корзинах для покупок, опросах и тестах)

Get.offAll(NextScreen());

Заметили, что вам не нужно было использовать контекст, чтобы делать что-либо из этого? Это одно из самых больших преимуществ использования Get. Благодаря этому вы можете без проблем выполнять все эти методы из класса контроллера.

Подробнее об управлении маршрутами

Get работает с именованными маршрутами, а также предлагает более низкий уровень контроля над вашими маршрутами! Здесь есть подробная документация.

Внедрение зависимостей

Get имеет простой и мощный менеджер зависимостей, который позволяет вам получить тот же класс, что и ваш BLoC или контроллер, всего одной строкой кода, без Provider context, без InheritedWidget:

Controller controller = Get.put(Controller()); // Вместо Controller controller = Controller();
  • Примечание: Если вы используете Get State Manager, обратите больше внимания на API привязок, который упростит подключение вашего представления к контроллеру.

Вместо того, чтобы создавать экземпляр вашего класса внутри класса, который вы используете, вы создаете его в экземпляре Get, что сделает его доступным во всем приложении. Таким образом, вы можете использовать свой контроллер (или BLoC) в обычном режиме.

Совет: Управление зависимостями Get не связано с другими частями пакета, поэтому, если, например, ваше приложение уже использует менеджер состояний (любой, не имеет значения), вам не нужно все это переписывать, вы можете использовать это внедрение зависимостей без проблем.

controller.fetchApi();

Представьте, что вы прошли через множество маршрутов и вам нужны данные, которые остались в вашем контроллере, вам понадобится менеджер состояний в сочетании с Provider или Get_it, верно? Только не с Get. Вам просто нужно попросить Get «найти» ваш контроллер, никаких дополнительных зависимостей вам не потребуется:

Controller controller = Get.find();
// Да, это выглядит как Магия! Get найдет ваш controller и доставит его вам. У вас может быть миллион созданных контроллеров, и Get всегда найдет нужный.

И тогда вы сможете восстановить данные вашего контроллера, которые были там получены:

Text(controller.textFromApi);

Подробнее о внедрении зависимостей

Более подробное объяснение управления зависимостями здесь

Утилиты

Интернационализация

Переводы

Переводы хранятся в виде карты пар "ключ-значение". Чтобы добавить собственные переводы, создайте класс и расширьте Translations.

import 'package:get/get.dart';

class Messages extends Translations {
  @override
  Map<String, Map<String, String>> get keys => {
        'en_US': {
          'hello': 'Hello World',
        },
        'de_DE': {
          'hello': 'Hallo Welt',
        }
      };
}

Использование переводов

Просто добавьте .tr к указанному ключу, и он будет переведен с использованием текущего значения Get.locale и Get.fallbackLocale.

Text('title'.tr);

Локализация

Передайте параметры в GetMaterialApp, чтобы определить языковой стандарт и переводы.

return GetMaterialApp(
    translations: Messages(), // ваши переводы
    locale: Locale('en', 'US'), // перевод будет осуществлен в этой локализации
    fallbackLocale: Locale('en', 'UK'), // установите резервную локализацию на случай если будет выбрана невалидный локализация.
);

Изменение локализации

Вызовите Get.updateLocale(locale), чтобы обновить локализацию. Затем переводы автоматически используют новый языковой стандарт.

var locale = Locale('en', 'US');
Get.updateLocale(locale);

Системная локализация

Чтобы узнать системную локализацию, вам следует использовать window.locale.

import 'dart:ui' as ui;

return GetMaterialApp(
    locale: ui.window.locale,
);

Изменение темы

Пожалуйста, не используйте виджет более высокого уровня, чем GetMaterialApp, для его обновления. Это может вызвать повторяющиеся ключи. Многие люди привыкли к старому подходу к созданию виджета «ThemeProvider» только для того, чтобы изменить тему вашего приложения, а это НЕ требуется с GetX ™.

Вы можете создать свою собственную тему и просто добавить ее в Get.changeTheme без повторяющегося кода:

Get.changeTheme(ThemeData.light());

Если вы хотите создать что-то вроде кнопки, которая изменяет тему, вы можете объединить для этого два API GetX ™:

  • API, который проверяет, используется ли темная тема.
  • И API смены темы.

Вы можете просто поместить это в onPressed:

Get.changeTheme(Get.isDarkMode? ThemeData.light(): ThemeData.dark());

Когда .darkmode активен, он переключится на light theme, и когда light theme станет активной, он изменится на dark theme.

Другие API

// получить текущие аргументы текущего экрана
Get.arguments

// получить аргументы предыдущего маршрута
Get.previousArguments

// получить имя предыдущего маршрута
Get.previousRoute

// получить чистый маршрут, например, чтобы узнать: rawRoute.isFirst()
Get.rawRoute

// получить доступ к Rounting API из GetObserver
Get.routing

// проверить, открыт ли снэкбар
Get.isSnackbarOpen

// открыт ли диалог
Get.isDialogOpen

// открыт ли bottomsheets
Get.isBottomSheetOpen

// удалить один маршрут
Get.removeRoute()

// возвращаться назад, пока данный предикат не выполнится
Get.until()

// идти вперед, удалив предыдущие маршруты, пока данный предикат не выполнится
Get.offUntil()

// перейти к следующему именованному маршруту, удалив предыдущие маршруты, пока данный предикат не выполнится
Get.offNamedUntil()

// проверить на какой платформе работает приложение
GetPlatform.isAndroid
GetPlatform.isIOS
GetPlatform.isMacOS
GetPlatform.isWindows
GetPlatform.isLinux
GetPlatform.isFuchsia

// проверить тип устройства
GetPlatform.isMobile
GetPlatform.isDesktop
// В вебе все платформы поддерживаются независимо!
// Можно узнать, работает ли приложение сейчас в браузере
// и на Windows, и на iOS, и на OSX, и на Android и так далее
GetPlatform.isWeb


// Эквивалент : MediaQuery.of(context).size.height,
// но неизменяемый.
Get.height
Get.width

// Текущий котекст навигации
Get.context

// Получить контекст показанного снэкбара/диалога/bottomsheets в любом месте вызова.
Get.contextOverlay

// Внимание: методы ниже являются расширениями класса BuildContext.
// Поскольку доступ к контексту есть в любом месте из вашего UI,
// вы можете использовать расширения в любом месте UI кода

// Если вам нужна изменяемая высота/ширина (например, настольное или браузерное окно, размер которого можно изменить), вам нужно использовать context
context.width
context.height

// Дает возможность определить половину экрана, треть и так далее.
// Полезно для отзывчивых приложений.
// param dividedBy (double) optional - default: 1
// param reducedBy (double) optional - default: 0
context.heightTransformer()
context.widthTransformer()

/// Схоже с MediaQuery.of(context).size
context.mediaQuerySize()

/// Схоже с MediaQuery.of(context).padding
context.mediaQueryPadding()

/// Схоже с MediaQuery.of(context).viewPadding
context.mediaQueryViewPadding()

/// Схоже с MediaQuery.of(context).viewInsets;
context.mediaQueryViewInsets()

/// Схоже с MediaQuery.of(context).orientation;
context.orientation()

/// Проверить, в горизонтальном ли режиме устройство
context.isLandscape()

/// Проверить, в вертикальном ли режиме устройство
context.isPortrait()

/// Схоже с to MediaQuery.of(context).devicePixelRatio;
context.devicePixelRatio()

/// Схоже с MediaQuery.of(context).textScaleFactor;
context.textScaleFactor()

/// Получить shortestSide экрана
context.mediaQueryShortestSide()

/// Вернет True, если ширина больше 800
context.showNavbar()

/// Вернет True, если меньшая сторона меньше 600p
context.isPhone()

/// Вернет True, если меньшая сторона больше 600p
context.isSmallTablet()

/// Вернет True, если меньшая сторона больше 720p
context.isLargeTablet()

/// Вернет True, если текущее устройство — Планшет
context.isTablet()

/// Возвращает value<T> в зависимости от размера экрана
/// Можно устанавливать значения для:
/// watch: Если меньшая сторона меньше 300
/// mobile: Если меньшая сторона меньше 600
/// tablet: Если меньшая сторона меньше 1200
/// desktop: Если ширина больше 1200
context.responsiveValue<T>()

Дополнительные глобальные настройки и ручные настройки

GetMaterialApp настраивает все за вас, но если вы хотите настроить Get вручную.

MaterialApp(
  navigatorKey: Get.key,
  navigatorObservers: [GetObserver()],
);

Вы также сможете использовать собственное промежуточное ПО в GetObserver, это ни на что не повлияет.

MaterialApp(
  navigatorKey: Get.key,
  navigatorObservers: [
    GetObserver(MiddleWare.observer) // Here
  ],
);

Вы можете создать Глобальные Настройки Для Get. Просто добавьте Get.config в ваш код прежде чем нажимать на любой из маршрутов. Или сделайте это прямо в GetMaterialApp

GetMaterialApp(
  enableLog: true,
  defaultTransition: Transition.fade,
  opaqueRoute: Get.isOpaqueRouteDefault,
  popGesture: Get.isPopGestureEnable,
  transitionDuration: Get.defaultDurationTransition,
  defaultGlobalState: Get.defaultGlobalState,
);

Get.config(
  enableLog = true,
  defaultPopGesture = true,
  defaultTransition = Transitions.cupertino
)

При желании, вы сможете перенаправить все сообщения из Get. Если вы хотите использовать свой любимый пакет для логирования и собирать логи там:

GetMaterialApp(
  enableLog: true,
  logWriterCallback: localLogWriter,
);

void localLogWriter(String text, {bool isError = false}) {
  // передайте сообщение вашей любимой log-библиотеке
  // но учитывайте, что даже если enableLog: false, сообщения все равно будут передаваться сюда
  // узнать значение этого флага можно с помощью GetConfig.isLogEnable
}

Локальные виджеты состояния

Эти виджеты позволяют управлять одним значением, сохраняя состояние эфемерным и локальным. У нас есть варианты для Reactive и Simple. Например, вы можете использовать их для переключения obscureText в TextField, возможно, для создания кастомного ExpandablePanel или, возможно, для изменения текущего индекса в BottomNavigationBar при изменении содержимого body в Scaffold.

ValueBuilder

Упрощение StatefulWidget который работает с вызовом .setState принимающим обновленное значение.

ValueBuilder<bool>(
  initialValue: false,
  builder: (value, updateFn) => Switch(
    value: value,
    onChanged: updateFn, // такая же сигнатура! Вы можете использовать ( newValue ) => updateFn( newValue )
  ),
  // Если нужно вызвать что-то вне метода builder
  onUpdate: (value) => print("Значение обновлено: $value"),
  onDispose: () => print("Виджет удален"),
),

ObxValue

Похож на ValueBuilder, но это реактивная версия, вы передаёте Rx экземпляр (помните волшебный .obs?) и автоматически обновляетесь... разве это не великолепно?

ObxValue((data) => Switch(
        value: data.value,
        onChanged: data, // У Rx есть _callable_ функция! Вы можете использовать (flag) => data.value = flag,
    ),
    false.obs,
),

Полезные советы

.observables (наблюдатели) (также известные как Rx-типы) имеют широкий спектр внутренних методов и операторов

Очень распространено мнение, что свойство с .obs ЯВЛЯЕТСЯ действительным значением... но не ошибайтесь! Мы избегаем объявления типа переменной, потому что компилятор Dart достаточно умен, и код выглядит чище, но:

var message = 'Привет, мир'.obs;
print( 'Тип "$message" — ${message.runtimeType}');

Даже если message выводит значение String, его тип - RxString!

Итак, вы не сможете сделать message.substring( 0, 4 ). Вы должны получить доступ к реальному value внутри observable: Самый "используемый способ" это .value, но, знаете ли вы, что вы также можете использовать ...

final name = 'GetX'.obs;
// "обновляет" поток только если значение отличается от текущего.
name.value = 'Хей';

// Все свойства Rx являются "вызываемыми" и возвращают новые значения.
// но это не работает с `null`: UI не будет перестроен.
name('Привет');

// как геттер, напечатает 'Привет'.
name() ;

/// числа:

final count = 0.obs;

// Вы можете использовать все неизменяемые операции с числами!
count + 1;

// Осторожно! Это можно использовать только если `count` не final, а var
count += 1;

// Сравнения так же работают:
count > 2;

/// логические:

final flag = false.obs;

// переключает значение между true/false
flag.toggle();


/// все типы:

// обнуляет значение переменной `value`.
flag.nil();

// Все toString(), toJson() операции применяются к `value`
print( count ); // вызывает `toString()` внутри RxInt

final abc = [0,1,2].obs;
// Преобразует значение в json массив, выводит RxList
// Json поддерживается всеми Rx типами!
print('json: ${jsonEncode(abc)}, тип: ${abc.runtimeType}');

// RxMap, RxList и RxSet являются особенными Rx типами: они расширяют нативные типы.
// Но вы можете работать со списком как и с обычным списком, хоть и реактивным!
abc.add(12); // добавлеет 12 в список, and ОБНОВЛЯЕТ поток.
abc[3]; // как списки, возвращает значение с индексом 3.


// Сравнение равенства работает с Rx и с его value, но хэш код всегда берется у value
final number = 12.obs;
print( number == 12 ); // печатает true

/// Кастомные Rx Модели:

// toJson(), toString() передаются child, так что вы можете перегрузить эти методы в нем, и вызвать print напрямую.

class User {
    String name, last;
    int age;
    User({this.name, this.last, this.age});

    @override
    String toString() => '$name $last, возраст: $age';
}

final user = User(name: 'Джон', last: 'Доу', age: 33).obs;

// `user` – "реактивный", но его свойства – НЕТ!
// Так что если мы обновим что-либо внутри user...
user.value.name = 'Рой';
// Виджет перестроен не будет!
// `Rx` не знает, изменили ли вы что-то у user.
// Так что для кастомных классов вам нужно явно "уведомлять" об изменении.
user.refresh();

// или мы можем использовать метод `update()`!
user.update((value){
  value.name='Рой';
});

print( user );

GetView

Я люблю этот виджет, он такой простой, но такой полезный!

Это const Stateless виджет, который имеет геттер controller для зарегистрированного Controller, вот и всё.

 class AwesomeController extends GetxController {
   final String title = 'Моя Удивительная View';
 }

  // ВСЕГДА передавайте `Тип` вашего контроллера!
 class AwesomeView extends GetView<AwesomeController> {
   @override
   Widget build(BuildContext context) {
     return Container(
       padding: EdgeInsets.all(20),
       child: Text( controller.title ), // просто вызовите `controller.что-то`
     );
   }
 }

GetWidget

Большинство людей понятия не имеют об этом виджете или путаются при его применении. Вариант его использования редок, но конкретен: он кэширует Controller. Поэтому из-за cache, он не может быть const Stateless.

Итак, когда вам нужно «кэшировать» контроллер?

В случаях использования другой "не распространённой" фичи GetX: Get.create().

Get.create(()=>Controller()) будет создавать новый Controller каждый раз при вызове Get.find<Controller>(),

Это тот самый случай, когда GetWidget блистает... поскольку вы можете использовать его, например, для хранения списка элементов Todo. Итак, если виджет будет «перестроен», он сохранит тот же экземпляр контроллера.

GetxService

Этот класс похож на GetxController, у него такой же жизненный цикл ( onInit(), onReady(), onClose()). Но внутри нет никакой «логики». Он просто уведомляет систему GetX Dependency Injection о том, что этот подкласс нельзя удалить из памяти.

Так что очень полезно держать ваши «Сервисы» всегда доступными и активными с помощью Get.find(). Например: ApiService, StorageService, CacheService.

Future<void> main() async {
  await initServices(); /// ПОДОЖДИТЕ ИНИЦИАЛИЗАЦИЮ СЕРВИСОВ.
  runApp(SomeApp());
}

/// Умным решением будет проинициализировать сервисы перед вызовом runApp,
/// поскольку вы можете контроллировать процесс инициализации
/// (может, вам нужно загрузить конфигурацию Темы, ключи API, язык, определенный пользователем...
/// Загружайте SettingService прежде чем запускать ApiService.
/// Таким образом GetMaterialApp() принимает параметры напрямую, и ему не нужно будет перезагружаться
void initServices() async {
  print('запуск сервисов ...');
  /// Здесь вы инициализируете get_storage, hive, shared_pref,
  /// или что-либо другое асинхронное.
  await Get.putAsync(() => DbService().init());
  await Get.putAsync(SettingsService()).init();
  print('Все сервисы запущены...');
}

class DbService extends GetxService {
  Future<DbService> init() async {
    print('$runtimeType задержка 2 секунды');
    await 2.delay();
    print('$runtimeType готов!');
    return this;
  }
}

class SettingsService extends GetxService {
  void init() async {
    print('$runtimeType задержка 1 секунду');
    await 1.delay();
    print('$runtimeType готов!');
  }
}

Единственный способ удалить GetxService - использовать Get.reset(), который похож на «горячую перезагрузку» вашего приложения. Так что помните, если вам нужен постоянный экземпляр класса в течение всего жизненного цикла вашего приложения, используйте GetxService.

Критические изменения по сравнению с версией 2.0

1- Rx типы:

До После
StringX RxString
IntX RxInt
MapX RxMap
ListX RxList
NumX RxNum
DoubleX RxDouble

RxController и GetBuilder теперь объединены, вам больше не нужно запоминать, какой контроллер вы хотите использовать, просто используйте GetxController, он будет работать как для простого управления состоянием, так и для реактивного.

2- NamedRoutes До:

GetMaterialApp(
  namedRoutes: {
    '/': GetRoute(page: Home()),
  }
)

Сейчас:

GetMaterialApp(
  getPages: [
    GetPage(name: '/', page: () => Home()),
  ]
)

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

GetStorage box = GetStorage();

GetMaterialApp(
  getPages: [
    GetPage(name: '/', page:(){
      return box.hasData('token') ? Home() : Login();
    })
  ]
)

Почему Getx?

1- Много раз после обновления Flutter многие из ваших пакетов ломались. Иногда случаются ошибки компиляции, часто возникают ошибки, на которые до сих пор нет ответов, и разработчику необходимо знать, откуда возникла ошибка, отслеживать ошибку, только затем попытаться открыть проблему в соответствующем репозитории и увидеть, как проблема решена. Get централизует основные ресурсы для разработки (управление состоянием, зависимостями и маршрутами), позволяя вам добавить один пакет в свой pubspec и начать работу. После обновления Flutter единственное, что вам нужно сделать, это обновить зависимость Get и приступить к работе. Get также решает проблемы совместимости. Как часто бывало, что одна версия пакета несовместима с другой, потому что одна использует зависимость в одной версии, а другая - в другой? Это не проблема при использовании Get, поскольку все находится в одном пакете и полностью совместимо.

2- Flutter - это просто, Flutter - это невероятно, но у Flutter все еще некоторый шаблонный код, который может быть нежелательным для большинства разработчиков, например Navigator.of(context).push (context, builder [...]. Get упрощает разработку. Вместо того, чтобы писать 8 строк кода для вызова маршрута, вы можете просто сделать это: Get.to(Home()) и всё готово, вы перейдёте на следующую страницу. Динамические URL-адреса - это действительно болезненная вещь, которую нужно решать во Flutter в настоящее время, а с GetX это элементарно. Управление состояниями во Flutter и управление зависимостями также вызывает много споров, поскольку в pub есть сотни паттернов. Но нет ничего проще, чем добавить «.obs» в конец вашей переменной и поместить ваш виджет внутри Obx, и всё, все обновления этой переменной будут автоматически обновляться на экране.

3- Лёгкость, не беспокоясь о производительности. Производительность Flutter уже потрясающая, но представьте, что вы используете диспетчер состояний и локатор для распределения классов блоков / хранилищ / контроллеров / и других классов. Вам придётся вручную вызывать исключение этой зависимости, когда она вам не нужна. Но вы когда-нибудь думали о том, чтобы просто использовать свой контроллер, и когда он больше никем не использовался, он просто был бы удален из памяти? Это то, что делает GetX. Благодаря SmartManagement всё, что не используется, удаляется из памяти, и вам не нужно беспокоиться ни о чем, кроме программирования. Вы будете уверены, что потребляете минимум необходимых ресурсов, даже не создав для этого логики.

4- Действительное разделение. Вы могли слышать о концепции разделения представления от бизнес логики. Это не исключительная особенность BLoC, MVC, MVVM и тд, любой стандарт реализует эту концепцию. Однако во Flutter возможно ослабление этой концепции из-за необходимости использования контекста. Если вам нужен контекст для поиска InheritedWidget, он вам нужен в представлении, либо нужно передать контекст как параметр. Мы считаем это решение очень уродливым, и для работы в команде мы всегда будем зависеть от логики представления (View). Getx - необычный подход со стандартным доступом, который хоть и не запрещает использование StatefulWidgets, InitState, и т.д., всегда имеет более чистый аналог. У контроллеров есть жизненные циклы, и когда вам нужно сделать, например, запрос APIREST, вы не зависите ни от чего в представлении. Вы можете использовать onInit для инициирования http-вызова, и когда данные поступят, переменные будут заполнены. Поскольку GetX полностью реактивен (действительно реактивен и работает с потоками), после заполнения элементов все виджеты, использующие эту переменную, будут автоматически обновлены в представлении. Это позволяет людям с опытом работы с пользовательским интерфейсом работать только с виджетами и не отправлять в бизнес-логику ничего, кроме пользовательских событий (например, нажатия кнопки), в то время как люди, работающие с бизнес-логикой, смогут создавать и тестировать бизнес-логику отдельно.

Эта библиотека всегда будет обновляться и реализовывать новые функции. Не стесняйтесь предлагать PR.

Сообщества

Каналы сообщества

У GetX очень активное и готовое к взаимовыручке сообщество. Если у вас есть вопросы или вы хотите получить какую-либо помощь относительно использования этого фреймворка, присоединяйтесь к нашим каналам сообщества, на ваш вопрос ответят быстро. Этот репозиторий предназначен исключительно для открытия проблем и запроса ресурсов, но не стесняйтесь быть частью сообщества GetX.

Slack Discord Telegram
Get on Slack Discord Shield Telegram

Как внести свой вклад

Хотите внести свой вклад в проект? Вы будем рады отметить вас как одного из наших соавторов. Вот несколько направлений, где вы можете сделать Get (и Flutter) лучше.

  • Помощь в переводе readme на другие языки.
  • Добавление документации в readme (многие функции Get еще не задокументированы).
  • Напишите статью или сделайте видео, обучающие использованию Get (они будут вставлены в Readme и в будущем в нашу Wiki).
  • Предложите PRs для кода/тестов.
  • Новые фичи.

Приветствуется любой вклад!

Статьи и видео