Please open Telegram to view this post
VIEW IN TELEGRAM
❤4👍2
Какие три основных подхода существуют для работы с иконками во Flutter?
Anonymous Quiz
4%
PNG, JPG, GIF
60%
Icon Fonts, SVG, Vector Graphics
34%
Material Icons, Cupertino Icons, Font Awesome
2%
Bitmap, Vector
Какой виджет позволяет дочернему элементу выходить за границы родителя?
Anonymous Quiz
84%
OverflowBox
3%
AspectRatio
10%
Expanded
2%
Align
Какие модификаторы можно комбинировать?
Anonymous Quiz
22%
base и final
27%
abstract и base
12%
sealed и base
39%
abstract и mixin
Какой Sliver позволяет вставить обычный виджет в CustomScrollView?
Anonymous Quiz
15%
SliverList
76%
SliverToBoxAdapter
4%
SliverAppBar
5%
SliverGrid
За этот год во @flutterfriendly вышло 222 публикации, а вы поставили более 3800 реакций. Решили вспомнить посты, которые вы больше всего читали и которыми активно делились за 2025 год:
Аудит безопасности мобильных приложений: виды и этапы
Использование ARB-формата
Обновление Android Studio без ошибок
Как пользоваться режимом выбора виджетов
Пакет meta
Оптимизация списков: как сделать скролл плавным и эффективным
Виджеты для управления размерами
Работа с иконками
Библиотека dartx
FutureOr в Dart
gRPC во Flutter: эффективная коммуникация между клиентом и сервером
Модификаторы классов в Dart
Тестирование кода: виды и для чего это нужно
Режимы сборки: debug, profile и release
Friflex Flutter Starter
Паттерн Strategy
Запись митапа: способы темизации и кастомизации мобильных приложений
Создание виджетов поверх существующего интерфейса
Определение местоположение пользователя: интеграция в приложение
Как быстро развернуть сайт документации с помощью Docusaurus
Адаптивная верстка: что это такое и как реализовать
Утечки памяти во Flutter-приложениях
Техническое собеседование: как подготовиться начинающим разработчикам
Hot Restart и Hot Reload: в чем отличия и как работают
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥9❤4
Какой принцип SOLID нарушен, если класс UserManager одновременно валидирует данные, сохраняет в БД и отправляет email?
Anonymous Quiz
2%
Принцип открытости/закрытости (O)
96%
Принцип единственной ответственности (S)
2%
Принцип инверсии зависимостей (D)
1%
Принцип подстановки Лисков (L)
Что из этого НЕ является Ephemeral state?
Anonymous Quiz
4%
Состояние текущей вкладки в TabBar
11%
Позиция скролла в ListView
71%
Данные пользователя из API
14%
Состояние анимации
Библиотека Equatable помогает:
Anonymous Quiz
5%
Упростить работу с State Management
85%
Упростить сравнение объектов по значению
8%
Создавать immutable объекты
2%
Генерировать тесты автоматически
Что означает TDD?
Anonymous Quiz
8%
Type-Driven Development
5%
Time-Delayed Deployment
1%
Top-Down Design
85%
Test-Driven Development
Dart FFI позволяет:
Anonymous Quiz
95%
Вызывать нативный C/C++ код из Dart
0%
Создавать красивые интерфейсы
3%
Работать с Firebase
2%
Ускорять компиляцию
Какой виджет лучше всего подходит для длинных списков с большим количеством простых элементов?
Anonymous Quiz
14%
SingleChildScrollView
13%
CustomScrollView
4%
Column
69%
ListView
Когда объект может быть удалён Garbage Collector’ом?
Anonymous Quiz
1%
Сразу после создания
5%
При переходе на новый экран
92%
Когда на объект больше нет ссылок
1%
Только после ручного вызова GC
Какой ключ лучше использовать для элементов списка с уникальным id из объекта item?
Anonymous Quiz
19%
UniqueKey
72%
ValueKey(item.id)
4%
GlobalKey
5%
ObjectKey(item)
Что произойдет, если вы измените метод initState() в StatefulWidget и примените Hot Reload?
Anonymous Quiz
8%
Новый код initState() будет выполнен сразу
22%
Виджет будет полностью пересоздан, initState() вызовется
67%
initState() не вызовется, старое состояние сохранится
4%
Приложение полностью перезапустится
❤2
Сегодня поговорим про push‑уведомления в реальном проекте: как работать с FCM, показывать локальные уведомления в foreground, обрабатывать background‑события, реализовать deep links по клику и корректно запрашивать разрешения.
Так как это первая статья в новом году, поздравляю всех с праздниками! Желаю вам продуктивного и приятного 2026‑го: чтобы баги фиксились легко, а фичи шли в прод. Уже все вернулись к работе или кто‑то все еще лежит на диване?
Что и зачем:
◾️FCM (Firebase Cloud Messaging) — транспорт: доставляет уведомления/дату на устройство. Поддерживает notification (авто‑показ) и data‑messages (передача произвольных данных)
◾️flutter_local_notifications — показывает локальное нотификационное состояние, полезно, когда приложение на foreground (FCM обычно не показывает системное уведомление, если приложение активно)
◾️Deep links — позволяют при клике на уведомление перейти в конкретный экран приложения (через data payload или динамические ссылки)
Код: инициализация и обработка
Пакеты: firebase_core, firebase_messaging, flutter_local_notifications, (go_router / navigatorKey для навигации).
Простой пример:
// main.dart (сокращённо)
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:firebase_messaging/firebase_messaging.dart';
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
final FlutterLocalNotificationsPlugin localNotif = FlutterLocalNotificationsPlugin();
Future<void> _bgHandler(RemoteMessage m) async {
await Firebase.initializeApp();
// Лёгкая логика: запись в БД или планирование локальной нотификации
print('BG message ${m.messageId}');
}
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
FirebaseMessaging.onBackgroundMessage(_bgHandler);
await localNotif.initialize(
const InitializationSettings(
android: AndroidInitializationSettings('@mipmap/ic_launcher'),
iOS: DarwinInitializationSettings(),
),
onDidReceiveNotificationResponse: (resp) {
final p = resp.payload;
if (p != null) navigatorKey.currentState?.pushNamed(p);
},
);
runApp(MyApp());
}
final GlobalKey<NavigatorState> navigatorKey = GlobalKey();
class MyApp extends StatefulWidget { @override State createState() => _MyAppState(); }
class _MyAppState extends State<MyApp> {
final FirebaseMessaging fm = FirebaseMessaging.instance;
@override
void initState() {
super.initState();
_requestPermissions();
FirebaseMessaging.onMessage.listen(_onMessage);
FirebaseMessaging.onMessageOpenedApp.listen((m) => _handleData(m.data));
_checkInitialMessage();
}
Future<void> _requestPermissions() async {
if (Platform.isIOS) {
await fm.requestPermission(alert: true, badge: true, sound: true);
} else {
// Android 13+: POST_NOTIFICATIONS нужно в Manifest + runtime request (permission_handler)
await fm.requestPermission();
}
}
void _onMessage(RemoteMessage m) {
// в foreground показываем локальную нотификацию
final t = m.notification?.noscript ?? m.data['noscript'];
final b = m.notification?.body ?? m.data['body'];
localNotif.show(m.hashCode, t, b, const NotificationDetails(
android: AndroidNotificationDetails('ch', 'Channel', importance: Importance.max),
), payload: m.data['deeplink']);
}
Future<void> _checkInitialMessage() async {
final m = await fm.getInitialMessage();
if (m != null) _handleData(m.data);
}
void _handleData(Map<String, dynamic> d) {
final deeplink = d['deeplink'] ?? d['url'] ?? d['screen'];
if (deeplink != null) navigatorKey.currentState?.pushNamed(deeplink);
}
@override
Widget build(BuildContext c) => MaterialApp(navigatorKey: navigatorKey, home: Scaffold(body: Center(child: Text('Ready'))));
}
Продолжение — в комментариях 👇
Please open Telegram to view this post
VIEW IN TELEGRAM
❤5⚡3👍1🔥1
This media is not supported in your browser
VIEW IN TELEGRAM
Ну-ка признавайтесь, кто всю неделю прокрастинировал вместо работы? А кто виноват? Конечно, новогодние праздники! Сегодня поговорим о том, как же максимально мягко войти в этот привычный, но давно забытый рабочий режим.
1 шаг. Пообщаться с коллегами
Всем нам непросто возвращаться к работе. Поговорите об этом! Немного юмора и обсуждений самых приятных воспоминаний с каникул легко поднимут настроение и настроют на позитивную волну.
2 шаг. Восстановить память
Наверняка, почти никто из вашей команды полноценно не помнит, какие проблемы и вопросы остались с прошлого года. Поэтому перед тем, как приступить к работе, синхронизируйтесь с коллегами.
Посмотрите доску задач, вспомните, какие незакрытые моменты были отложены на новый год. В идеале — провести планирование с командой, сформировать список задач, расставить приоритеты. Как только вы четко увидите список задач, вам будет проще настроиться на работу.
3 шаг. Начните с простого
Если у вас есть возможность самостоятельно определять порядок выполняемых задач, воспользуйтесь ею. Возьмите в первую очередь самые простые и короткие задачи. Сначала закроете одну, потом вторую, а дальше двигаться по инерции будет проще.
4 шаг. Чаще делайте перерывы
Конечно, звучит не очень продуктивно. Но после долгого отдыха мозгу тяжело долго держать фокус. Давайте ему возможность разгрузиться — короткие перерывы по 5-10 минут помогут в этом. Но не слишком злоупотребляйте, есть риск снова уйти в прокрастинацию.
5 шаг. Восстановите привычный режим жизни.
Чаще всего после длительного перерыва страдает не только работа, но и другие сферы жизни. Верните в жизнь свои старые привычки, приостановленные на праздники. Ходили в спортзал? Вернитесь к тренировкам. Занимались английским? Возобновите занятия. Ложились спать в 22:00? Самое время наладить режим.
Делитесь в комментариях своими советами!
Please open Telegram to view this post
VIEW IN TELEGRAM
❤5🔥3👍2😍1
This media is not supported in your browser
VIEW IN TELEGRAM
Понимать код, а не копировать
Привет, это Катя, Flutter Dev Friflex. Сегодня — короткая и практичная заметка о том, почему важно понимать, что делает каждое поле и компонент в проекте, регулярно «проваливаться» в пакеты и отслеживать версии, чтобы избежать сюрпризов в проде.
Почему это критично?
▪️Непонимание контракта поля/метода = баги, неожиданные побочные эффекты, уязвимости
▪️Непроверенные апдейты зависимости = сломанные сборки и runtime‑ошибки
▪️Понимание реализации помогает правильно тестировать, оптимизировать и писать корректную миграцию при изменениях
Куда смотреть?
▫️pub.dev: дата релиза, репозиторий, example, issue tracker
▫️GitHub: README, CHANGELOG.md, Releases/Tags, open/closed issues и PR
▫️Исходники: «Go to definition» в IDE, искать @deprecated, читать реализацию конструктора/методов
▫️Тесты и пример в пакете — часто показывают ожидаемое поведение
На что обращать внимание в поле/компоненте?
▪️Контракт: допустимые входы/выходы, nullable/required, default‑значения
▪️Эффекты: I/O, глобальное состояние, запуск таймеров, необходимость dispose()
▪️Производительность: rebuild/rerender cost, аллокации, потокобезопасность
▪️Депрексации и migration notes: @deprecated и changelog
Практики по версиям и апдейтам
▫️Понимай major = breaking changes. Читай CHANGELOG перед апдейтом
▫️Используй pubspec.lock для воспроизводимости билдов.
Команды: flutter pub outdated; flutter pub deps --style=compact
▫️CI: автоматические тесты после обновления зависимостей
Краткий процесс обновления зависимости
▪️Исследовать пакет (README, changelog, issues, example)
▪️В feature‑ветке обновить зависимость и запустить flutter pub get
▪️Прогнать unit & integration тесты локально и в CI
▪️Развернуть на стейдже
▪️Мониторинг (Crashlytics/Sentry)
▪️Быстрый откат при регрессии
Культура в команде
▫️Составить шаблон PR
▫️Назначать владельца критичных библиотек
▫️Регулярный dependency health check (реально желательно делать)
▫️Обучать команду читать исходники и миграционные заметки
Какие еще практики и инструменты вы используете, чтобы безопасно работать со сторонними зависимостями и глубоко понимать чужой код?
Привет, это Катя, Flutter Dev Friflex. Сегодня — короткая и практичная заметка о том, почему важно понимать, что делает каждое поле и компонент в проекте, регулярно «проваливаться» в пакеты и отслеживать версии, чтобы избежать сюрпризов в проде.
Почему это критично?
▪️Непонимание контракта поля/метода = баги, неожиданные побочные эффекты, уязвимости
▪️Непроверенные апдейты зависимости = сломанные сборки и runtime‑ошибки
▪️Понимание реализации помогает правильно тестировать, оптимизировать и писать корректную миграцию при изменениях
Куда смотреть?
▫️pub.dev: дата релиза, репозиторий, example, issue tracker
▫️GitHub: README, CHANGELOG.md, Releases/Tags, open/closed issues и PR
▫️Исходники: «Go to definition» в IDE, искать @deprecated, читать реализацию конструктора/методов
▫️Тесты и пример в пакете — часто показывают ожидаемое поведение
На что обращать внимание в поле/компоненте?
▪️Контракт: допустимые входы/выходы, nullable/required, default‑значения
▪️Эффекты: I/O, глобальное состояние, запуск таймеров, необходимость dispose()
▪️Производительность: rebuild/rerender cost, аллокации, потокобезопасность
▪️Депрексации и migration notes: @deprecated и changelog
Практики по версиям и апдейтам
▫️Понимай major = breaking changes. Читай CHANGELOG перед апдейтом
▫️Используй pubspec.lock для воспроизводимости билдов.
Команды: flutter pub outdated; flutter pub deps --style=compact
▫️CI: автоматические тесты после обновления зависимостей
Краткий процесс обновления зависимости
▪️Исследовать пакет (README, changelog, issues, example)
▪️В feature‑ветке обновить зависимость и запустить flutter pub get
▪️Прогнать unit & integration тесты локально и в CI
▪️Развернуть на стейдже
▪️Мониторинг (Crashlytics/Sentry)
▪️Быстрый откат при регрессии
Культура в команде
▫️Составить шаблон PR
▫️Назначать владельца критичных библиотек
▫️Регулярный dependency health check (реально желательно делать)
▫️Обучать команду читать исходники и миграционные заметки
Какие еще практики и инструменты вы используете, чтобы безопасно работать со сторонними зависимостями и глубоко понимать чужой код?
❤4🔥3🎉1
Один из самых частых запросов бизнеса — отобразить важные документы внутри приложения. Это может быть все, что угодно: от политики конфиденциальности и правил сервиса до персональных документов пользователей. И как показывает практика, чаще всего такие документы приходят в формате pdf.
Сегодня поговорим о том, как удобно отображать pdf-файлы во Flutter-приложении.
На pub.dev можно найти несколько похожих плагинов для показа pdf-файлов в приложении. Но сегодня рассмотрим один из самых популярных и мною любимых плагинов — syncfusion_flutter_pdfviewer.
Первое, что привлекает в этой библиотеке — возможность открыть файл из разных источников, не только из внутреннего хранилища. Рассмотрим разные варианты.
1️⃣
SfPdfViewer.networkЭтот метод позволяет загрузить файл по ссылке, достаточно передать соответствующий url. И что самое удобное — вы легко можете открыть даже защищенный паролем файл, так как метод дает возможность передать
passwordreturn Scaffold(
body: SfPdfViewer.network(
'https://cdn.syncfusion.com/content/PDFViewer/encrypted.pdf',
password: 'syncfusion',
),
);
2️⃣
SfPdfViewer.asset
Здесь можно открыть любой файл, вложенный в assets проектаreturn Scaffold(body: SfPdfViewer.asset('assets/files/test_file.pdf'))
3️⃣
SfPdfViewer.fileЭтот виджет дает возможность отобразить файл из локального хранилища устройства по пути
return Scaffold(
body: SfPdfViewer.file(
File('path_to_your_local_file'),
),
);
4️⃣
SfPdfViewer.memoryА этот позволяет отобразить файл, представленный в байтах
return Scaffold(
body: FutureBuilder(
future: _loadFromAsset('assets/files/test_file.pdf'),
builder: (context, snapshot) {
if (snapshot.hasData) {
return SfPdfViewer.memory(snapshot.data!);
} else {
return const CircularProgressIndicator();
}
},
),
);
...
Future<Uint8List> _loadFromAsset(String path) async {
final data = await rootBundle.load(path);
return data.buffer.asUint8List(data.offsetInBytes, data.lengthInBytes);
}
Еще одна причина попробовать этот плагин — вид файла можно легко настраивать с помощью дополнительных параметров. Например, можно задать начальные значения страницы и зума —
initialPageNumber и initialZoomLevel. А также цвет выделенного текста при поиске — otherSearchTextHighlightColor и currentSearchTextHighlightColorSfPdfViewer.network(
'https://cdn.syncfusion.com/content/PDFViewer/encrypted.pdf',
password: 'syncfusion',
initialPageNumber: 1,
initialZoomLevel: 1.0,
otherSearchTextHighlightColor: Colors.green.withValues(alpha: 0.5),
currentSearchTextHighlightColor: Colors.blue.withValues(alpha: 0.5),
),
Продолжение — в комментариях 👇
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥11❤4💯2❤🔥1🆒1
Привет, это Анна, Flutter Team Lead Friflex. В этой статье разобрала, как во Flutter реализовать поддержку deeplink-ов и универсальных ссылок и как управлять ими на уровне платформы.
Please open Telegram to view this post
VIEW IN TELEGRAM
Хабр
Deeplink-и во Flutter: динамические ссылки и app_links
Привет! Меня зовут Анна Ахлестова, я Flutter Team Lead в компании Friflex . Мобильные приложения, в том числе на Flutter, позволяют настраивать обработку различных ссылок. В этой статье я разберу, как...
🔥7❤4💯2