Flutter Friendly
1.03K subscribers
212 photos
77 videos
1 file
161 links
Канал Friflex о разработке на Flutter. Обновления, плагины, полезные материалы — превращаем знания в реальный опыт, доступный каждому разработчику.

🔗 Наш канал для разработчиков: @friflex_dev
🔗 Канал о продуктовой разработке: @friflex_product
Download Telegram
Привет, это Катя, Flutter-разработчик Friflex. Сегодня разберем концепцию BuildContext.

Что такое BuildContext?
BuildContext
— это специальный объект, который представляет собой ссылку на конкретное место виджета в дереве элементов. По сути, это идентификатор позиции виджета в иерархии приложения.

Каждый виджет при построении получает свой уникальный BuildContext. Именно через него виджет может взаимодействовать с другими частями дерева: получать доступ к родительским виджетам, темам, навигации и многому другому.

Как это работает на практике?
Когда мы пишем метод build(), мы всегда получаем параметр context:

@override
Widget build(BuildContext context) {
  return Container(
    child: Text('Привет'),
  );
}


Этот context и есть BuildContext. Он связывает наш виджет с конкретным элементом в дереве. Через него Flutter понимает, где именно находится виджет и как с ним работать.

Почему BuildContext так важен?
Возьмем простой пример — доступ к теме приложения:

final theme = Theme.of(context);

Метод Theme.of(context) использует BuildContext, чтобы подняться вверх по дереву виджетов и найти ближайший ThemeData. Без context это было бы невозможно — Flutter просто не знал бы, откуда начинать поиск.

То же самое происходит с навигацией:

Navigator.of(context).push(
  MaterialPageRoute(builder: (context) => NextScreen()),
);

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

Распространенная ошибка
Часто встречается ситуация, когда разработчик пытается использовать BuildContext до того, как виджет добавили в дерево, или после того, как его удалили. Например:

@override
Widget build(BuildContext context) {
  Future.delayed(Duration(seconds: 2), () {
    // Опасно! Context может быть уже невалидным
    showDialog(context: context, builder: (_) => AlertDialog());
  });
  return Container();
}


Если виджет удалят из дерева за эти две секунды, использование context приведет к ошибке. Для таких случаев стоит проверять mounted в StatefulWidget или использовать более безопасные подходы.

BuildContext и InheritedWidget
Особенно важную роль BuildContext играет при работе с InheritedWidget. Именно через context виджеты подписываются на изменения:

final data = MyInheritedWidget.of(context);


При таком вызове Flutter регистрирует зависимость текущего виджета от MyInheritedWidget через BuildContext. Когда InheritedWidget обновится, все зависимые от него виджеты будут автоматически перестроены.

❤️ — если было полезно
Please open Telegram to view this post
VIEW IN TELEGRAM
18
Привет, это Катя, Flutter Dev Friflex! Сегодня разберем, зачем нужны Keys во Flutter, как они работают и когда их стоит (и не стоит) использовать.

Что такое Key?
Key — идентификатор виджета, который помогает Flutter сопоставлять новые виджеты с уже существующими элементами при обновлении дерева.

Как Flutter сопоставляет виджеты без ключей
Когда Flutter получает новый список виджетов при ребилде, он пытается сопоставить их с существующими элементами по позиции и типу (runtimeType). Если порядок элементов изменился или виджеты одного типа поменялись местами, состояние может перескочить на другой элемент — потому что Flutter повторно использовал элемент по индексу.

Пример проблемы без ключей

import 'package:flutter/material.dart';

class ItemWidget extends StatefulWidget {
final String title;
ItemWidget(this.title);

@override
_ItemWidgetState createState() => _ItemWidgetState();
}

class _ItemWidgetState extends State<ItemWidget> {
int counter = 0;

@override
Widget build(BuildContext context) {
return ListTile(
title: Text('${widget.title} ($counter)'),
trailing: IconButton(
icon: Icon(Icons.add),
onPressed: () => setState(() => counter++),
),
);
}
}


При перестановке элементов состояния могут перепутаться

Типы
▫️ValueKey<T> — ключ по значению (идеален для id-модели).
▫️ObjectKey — сравнение по == объекта.
▫️UniqueKey — каждый раз новый ключ (заставляет создать новый Element; сбрасывает состояние).
▫️GlobalKey — глобальная уникальность + доступ к State/Context; использовать экономно (дорогой).

Когда использовать
▫️Динамические списки с добавлением/удалением/реордером — ValueKey(id).
▫️Формы, доступ к State извне — GlobalKey (только при необходимости).

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

Рекомендации
▫️Для сущностей с постоянным id — ValueKey(id).
▫️Если хотите сбросить состояние — UniqueKey.
▫️GlobalKey — только для специфических задач (формы, навигация, тесты).
▫️Если состояние перескакивает — сначала добавьте ключи, а не перестраивайте архитектуру.

И помните, правильный выбор ключа решает распространенные баги с состоянием 🦋
Please open Telegram to view this post
VIEW IN TELEGRAM
3🔥1
Привет! Это Анна, лидер Flutter-команды Friflex.

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

flutter_staggered_animations
Эта
библиотека позволит вам красиво анимировать отрисовку списков и сеток. Работает с виджетами ListView, GridView, Column и Row. Вид анимации и ее длительность можно задавать самостоятельно, есть возможность комбинировать эффекты между собой. В результате получаем интересную каскадную отрисовку каждого элемента последовательно.

liquid_glass_renderer
Эта
библиотека понравится тем, кому пришлась по душе новинка iOS 26 — эффект жидкого стекла. Проект довольно новый, но уже имеет несколько вариантов виджетов. Тут можно создать и единичные стеклянные формы, и формы из нескольких смешанных объектов.

Очень важно — в боевую версию внедрять его пока не стоит, об этом предупреждает и сам автор. Но потрогать на досуге и в личных проектах будет точно интересно.

И тут можно сразу вспомнить более стабильный аналог glass_kit. Он по функциональности, возможно, чуть проще, но все так же достоин внимания.

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

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

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

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

Использование очень простое — вам нужно обернуть виджет, который требует скелетона, в виджет из библиотеки и передать состояние включить/выключить. А вот дальше вы можете модифицировать вид скелетона так, как душе угодно. Рекомендую заглянуть в документацию, там много интересных примеров.

confetti
Хочется добавить праздника в проект? Пожалуйста, конфетти будут в самый раз!

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

❤️ — если присматриваетесь к одной из этих библиотек
21🔥1🤩1🤣1
😌ИИ-будущее: нас заменят?

Привет, это Катя, Flutter-разработчик Friflex! Сегодня коротко: про всплеск агентов и утилит вокруг них, модели, навыки, MCP и прочие инструменты.

Многие компании уже ищут ИИ-программистов или инженеров продукта, которые умеют не только писать код, но и проектировать и интегрировать агентов в продукт.

Ключевые игроки на рынке ИИ: Anthropic, OpenAI, Google (Vertex AI / PaLM), Microsoft, Meta, Hugging Face, Cohere, Mistral, Stability AI.

Понимаю, многие сейчас напряглись из‑за давления ИИ: страх потерять роль, ускоренные требования к навыкам, неопределенность задач. Именно поэтому важно не пугаться, а погружаться: изучать архитектуры агентов, безопасность, координацию (оркестрацию), CI/CD и продуктовый инжиниринг вокруг них.

Интересна ли вам эта тема? Если да, то дайте знать, какие моменты разобрать подробнее: выбор модели, архитектуру агентов, безопасность и приватность, управление навыками, CI/CD для агентов, кейсы инженера продукта или что-то еще? Пишите темы, а я соберу инфу ⬇️
Please open Telegram to view this post
VIEW IN TELEGRAM
5👍2
Привет! Это Анна, лидер Flutter-команды Friflex.

Если перед вами стоит задача добавить во Flutter-приложение аутентификацию по биометрии, с этим может помочь плагин local_auth. Сегодня разберем его функционал и принцип работы.

Библиотека помогает провести локальную аутентификацию с помощью настроек, которые есть на устройстве. Например, пин-кода, сканирования отпечатка пальца или идентификации по лицу (FaceID).

Все работает очень просто: плагин не проверяет код или лицо и отпечаток пальца самостоятельно. Он обращается в систему, запрашивает проверку, и возвращает в приложение простое булево значение. Разберем методы плагина подробнее ⬇️

Для начала нужно создать экземпляр класса LocalAuthentication. Через него будут выполняться все операции.

final localAuth = LocalAuthentication();


Метод isDeviceSupported() проверит наличие любого способа аутентификации на устройстве. А canCheckBiometrics() ответит, доступна ли аутентификация именно по биометрии.

final isDeviceSupported = await localAuth.isDeviceSupported();
final canAuthenticate = await localAuth.canCheckBiometrics;


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

final list = await localAuth.getAvailableBiometrics();


А здесь внимательно: getAvailableBiometrics вернет список только тех биометрических функций, которые настроены пользователем на устройстве. А флаг canAuthenticate просто покажет их наличие.

Дальше самое интересное — проверка. Она выполняется с помощью метода authenticate(). В него можно добавить строку с описанием причины запроса аутентификации. Этот текст пользователь увидит на экране. Также можно задавать ограничения. Например, установить true флаг biometricOnly. Тогда ввод системного пин-кода не будет запрашиваться.

final successAuth = await localAuth.authenticate(
localizedReason: 'ВОЙДИТЕ',
biometricOnly: true,
);


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

С вас ❤️, если было полезно
Please open Telegram to view this post
VIEW IN TELEGRAM
16🔥8🤩2
This media is not supported in your browser
VIEW IN TELEGRAM
🪙Привет! Это Анна, Friflex Flutter Team Lead

Знаете, как во Flutter-приложении получать информацию от аппаратных датчиков движения? Сейчас узнаете!

В этой задаче вам поможет плагин sensors_plus. Как описывают его разработчики — он дает возможность вашему Flutter-приложению обращаться к сенсорам устройства, таким как:
▪️ акселерометр
▪️ гироскоп
▪️ барометр
▪️ магнитометр

Как это работает?
Через плагин приложение обращается в платформу. Натив считывает данные с сенсоров и полученные данные передает во Flutter посредством Streams (потоков). В приложении же вам достаточно подписаться на необходимый поток с данными.

Библиотека дает возможность отслеживать данные по пяти основным событиям:

✔️AccelerometerEvent — ускорение устройства. Это событие не фильтрует гравитацию, поэтому в состоянии покоя покажет всегда 9.8 м/с² вверх

✔️UserAccelerometerEvent — в отличие от AccelerometerEvent отражает только фактическое ускорение устройства. Поток исключает гравитацию, что в состоянии покоя покажет 0

✔️GyroscopeEvent — вращение устройства

✔️MagnetometerEvent — данные окружающего магнитного поля.

✔️BarometerEvent — текущее атмосферное давление

Использовать очень просто. Достаточно подписаться на поток данных по необходимому событию.

late StreamSubscription<AccelerometerEvent> _accelerometerSubscription;
...
_accelerometerSubscription = accelerometerEventStream().listen((event) {
print('x: ${event.x}, y: ${event.y}, z: ${event.z}');
});


Не забывайте закрывать подписки
_accelerometerSubscription.cancel();


Для чего может быть полезно?
Представим, вам нужно сделать реализацию как в банках — при перевороте экрана требуется скрывать или открывать данные на экране. Или при тряске устройства небходимо выполнять перезапрос данных. Для всех этих задач sensors_plus точно будет полезен.
Please open Telegram to view this post
VIEW IN TELEGRAM
5🔥3🤩1
Всегда с нетерпением ждем этого дня, чтобы сделать подборку ИТ-мемов

Пусть поводов для улыбки будет больше 💛
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
7🔥6😁4👍2