This media is not supported in your browser
VIEW IN TELEGRAM
Google Play 2025: что нового для разработчиков и пользователей
Привет, это Катя, Flutter Dev Friflex. Недавно Google Play выпустил большую обнову, которая затронула разработчиков, игроков и обычных пользователей. Сегодня коротко расскажу про самое главное, а подробнее можно почитать тут.
👨💻 Для разработчиков
В Play Console появились новые метрики (предрегистрации, открытия страниц), библиотека для хранения креативов и даже кнопка, чтобы остановить проблемный релиз
Engage SDK теперь работает и в Play Store, а значит — больше персональных подборок и контента прямо на главной
В Play Games Services достижения стали заметнее — их видно в поиске и на карточках игр
🎮 Для игроков
В программе Play Points запустили Diamond District в Roblox — с эксклюзивным VIP-доступом и мерчем для Gold+
Google Play Games for PC добавил мультиаккаунты и мультиокна. Теперь можно играть сразу в несколько игр (или в одну, но с разных аккаунтов 😏)
На Google TV появились рейтинги и отзывы, а на часах (Wear OS) — персональные рекомендации циферблатов
🔒 Безопасность
Кампания Download Apps, Not Traps — теперь каждое приложение проходит больше 10 000 проверок безопасности
В Play Integrity API добавили новые защиты от взломов и злоупотреблений
💳 Платежи
Больше способов оплаты: PayPal в Сингапуре, Napas во Вьетнаме, Airtel в Кении и других странах
В Индонезии появился QRIS — новый стандарт для бесконтактных платежей
Подписки стали удобнее: можно покупать несколько сразу, есть напоминания о бенефитах и увеличенные grace-периоды. Для разработчиков — возможность ставить цены до $5000
🌍 Глобальные проекты
Google продолжает поддерживать стартапы по всему миру:
программы для студий в Корее, Индонезии, Индии и Латинской Америке
#WeArePlay — серия историй про разработчиков, например, про игру, которая помогла высадить 360 000 деревьев
В общем и целом, Google Play не стоит на месте — теперь тут больше возможностей для всех: и для игроков, и для разработчиков, и для тех, кто просто любит удобные и безопасные приложения.
💬 А что думаете вы по поводу этих обновлений?
Привет, это Катя, Flutter Dev Friflex. Недавно Google Play выпустил большую обнову, которая затронула разработчиков, игроков и обычных пользователей. Сегодня коротко расскажу про самое главное, а подробнее можно почитать тут.
👨💻 Для разработчиков
В Play Console появились новые метрики (предрегистрации, открытия страниц), библиотека для хранения креативов и даже кнопка, чтобы остановить проблемный релиз
Engage SDK теперь работает и в Play Store, а значит — больше персональных подборок и контента прямо на главной
В Play Games Services достижения стали заметнее — их видно в поиске и на карточках игр
🎮 Для игроков
В программе Play Points запустили Diamond District в Roblox — с эксклюзивным VIP-доступом и мерчем для Gold+
Google Play Games for PC добавил мультиаккаунты и мультиокна. Теперь можно играть сразу в несколько игр (или в одну, но с разных аккаунтов 😏)
На Google TV появились рейтинги и отзывы, а на часах (Wear OS) — персональные рекомендации циферблатов
🔒 Безопасность
Кампания Download Apps, Not Traps — теперь каждое приложение проходит больше 10 000 проверок безопасности
В Play Integrity API добавили новые защиты от взломов и злоупотреблений
💳 Платежи
Больше способов оплаты: PayPal в Сингапуре, Napas во Вьетнаме, Airtel в Кении и других странах
В Индонезии появился QRIS — новый стандарт для бесконтактных платежей
Подписки стали удобнее: можно покупать несколько сразу, есть напоминания о бенефитах и увеличенные grace-периоды. Для разработчиков — возможность ставить цены до $5000
🌍 Глобальные проекты
Google продолжает поддерживать стартапы по всему миру:
программы для студий в Корее, Индонезии, Индии и Латинской Америке
#WeArePlay — серия историй про разработчиков, например, про игру, которая помогла высадить 360 000 деревьев
В общем и целом, Google Play не стоит на месте — теперь тут больше возможностей для всех: и для игроков, и для разработчиков, и для тех, кто просто любит удобные и безопасные приложения.
Please open Telegram to view this post
VIEW IN TELEGRAM
❤4🔥4👍3
Поговорим об одном из самых распространенных плагинов для Flutter-приложений — cached_network_image. Думаю, уже многие с ним знакомы, но сегодня разберем как эффективно использовать его функционал.
cached_network_image — это плагин, который позволяет не только загружать и отображать изображения из сети, но кэшировать их на устройстве. Эта функция является его главным преимуществом перед стандартным Image.network.
Для его использования достаточно добавить в верстку виджет CachedNetworkImage и передать ему ссылку на изображение в поле
imageUrl
. CachedNetworkImage(
imageUrl: url,
),
Как мы все знаем, загрузка изображений из сети может занимать некоторое время, поэтому рекомендую добавлять индикатор загрузки. Самый простой вариант — использовать
placeholder
. Сюда вы можете добавить любой виджет для отображения загрузки, например, кастомный скелетон. CachedNetworkImage(
imageUrl: url,
placeholder: (context, url) => const AppSkeleton(),
),
Если вам необходимо отображать прогресс загрузки, идеальным решением вместо
placeholder
станет progressIndicatorBuilder
. Он с помощью данных класса DownloadProgress даст вам полный доступ к информации о размере изображения и текущему загруженному объемуCachedNetworkImage(
imageUrl: url,
progressIndicatorBuilder: (context, url, progress) {
return AppProgressIndicator(progressValue: progress.progress);
},
),
Также важно не забывать, что загрузка может прерваться из-за ошибки. На такой случай рекомендую использовать
errorWidget
, который позволит отобразить заглушку. А для отслеживания самой ошибки будет полезен колбэк errorListener
. Он оповестит вас о том, какая возникла ошибка и в какой момент. CachedNetworkImage(
imageUrl: url,
errorWidget: (context, url, error) => AppErrorView(),
errorListener: (error) => print(error),
),
CachedNetworkImage также имеет очень много дополнительных параметров для оформления изображения, которые могут потребоваться вам для кастомизации. Но еще одна немаловажная функция — это управление кэшем с помощью
cacheManager
. Для этого вам потребуется дополнительно подключить в проект flutter_cache_manager. Библиотека дает доступ к объекту DefaultCacheManager, который в свою очередь необходимо передать в CachedNetworkImage.
final cacheManager = DefaultCacheManager();
...
CachedNetworkImage(
imageUrl: url,
cacheManager: cacheManager,
),
Теперь через cacheManager можно выполнять всевозможные манипуляции с кэшированными изображениями: извлекать или удалять по ключу, очищать кэш полностью.
await cacheManager.emptyCache(); // полная очистка кэша
await cacheManager.removeFile(key); // удаление конкретного файла из кэша
await cacheManager.getFileFromCache(key); // извлечение конкретного файла из кэша
А если функционала дефолтного менеджера вам недостаточно, можно создать свой кастомный. Он позволит настроить дополнительные параметры по кэшированию, например, срок жизни кэша или максимальное количество объектов в нем.
final customCacheManager = CacheManager(
Config(
'customCacheKey',
stalePeriod: const Duration(days: 7), // срок жизни кэша
maxNrOfCacheObjects: 100, // максимальное количество объектов в кэше
)
);
...
CachedNetworkImage(
imageUrl: url,
cacheManager: customCacheManager,
),
❤️ — если было полезно
Please open Telegram to view this post
VIEW IN TELEGRAM
❤18👍3🔥3😍1
Всем привет! Это Роза, Flutter Dev Friflex 👋
Сегодня расскажу про пакет, с помощью которого можно легко настроить запросы к вашему бэкенду — dart_frog. Он упрощает создание роутингов благодаря автоматической генерации кода. В этом посте покажу пару команд и расскажу основные моменты при работе с пакетом.
🐸 Как начать
Чтобы начать работу с dart_frog, сначала необходимо установить зависимость. Далее можно работать с командами пакета
Для создания проекта используйте:
В результате у вас создастся структура проекта, которая включает в себя DockerFile.
Основная логика обработки запросов в Dart Frog строится на маршрутах (routes). Каждый маршрут соответствует определенному пути и методу HTTP, и чтобы его добавить необходимо создать файл-обработчик в директории routes/.
Например, чтобы добавить POST /api/localization_key/export, создайте файл вручную:
Или используйте команду:
Далее внутри созданного роута реализуйте функцию:
RequestContext позволяет получить доступ к входящему запросу, а также к зависимостям, представленным контексту запроса.
🐸 Middleware
В Dart Frog middleware реализуется как функция, которая оборачивает обработчик маршрута и возвращает новый обработчик с дополнительной логикой.
Middleware добавляется в проект в виде файла с названием _middleware.dart.
Создать middleware можно также с помощью команды:
После добавления или изменения middleware необходимо перезапустить генерацию кода для применения изменений.
Пару важных моментов:
◽️Если файл _middleware.dart находится в папке маршрута без вложенности, middleware применяется ко всем маршрутам на этом уровне
◽️Чтобы middleware применялся только к определенным маршрутам, необходимо создать _middleware.dart внутри соответствующей папки маршрутов
◽️ Если middleware создан в произвольной, не связанной с маршрутом папке, он применен не будет
Структура middleware выглядит таким образом:
Кроме маршрутов и middleware, часто нужно работать с заголовками запросов. В Dart Frog это реализуется так:
Когда вы настроили маршруты, middleware и работу с заголовками, нужно сгенерировать код маршрутов, чтобы сервер мог их использовать.
Для этого используйте:
Это создает сгенерированный код маршрутов в директории build/, который используется сервером (bin/server.dart).
❗️ При работе с dart_frog важно поддерживать правильную вложенность папок, чтобы маршруты сгенерировались корректно. Более подробно можно прочитать в документации Dart Frog.
Сегодня расскажу про пакет, с помощью которого можно легко настроить запросы к вашему бэкенду — dart_frog. Он упрощает создание роутингов благодаря автоматической генерации кода. В этом посте покажу пару команд и расскажу основные моменты при работе с пакетом.
🐸 Как начать
Чтобы начать работу с dart_frog, сначала необходимо установить зависимость. Далее можно работать с командами пакета
Для создания проекта используйте:
dart_frog build
В результате у вас создастся структура проекта, которая включает в себя DockerFile.
Основная логика обработки запросов в Dart Frog строится на маршрутах (routes). Каждый маршрут соответствует определенному пути и методу HTTP, и чтобы его добавить необходимо создать файл-обработчик в директории routes/.
Например, чтобы добавить POST /api/localization_key/export, создайте файл вручную:
lib/routes/api/localization_key/export.dart
Или используйте команду:
dart_frog new route "/api/localization_key/export"
Далее внутри созданного роута реализуйте функцию:
Future<Response> onRequest(RequestContext context) async {
// Логика обработки запроса
return Response.json(body: {'message': 'Экспорт данных'});
}
RequestContext позволяет получить доступ к входящему запросу, а также к зависимостям, представленным контексту запроса.
🐸 Middleware
В Dart Frog middleware реализуется как функция, которая оборачивает обработчик маршрута и возвращает новый обработчик с дополнительной логикой.
Middleware добавляется в проект в виде файла с названием _middleware.dart.
Создать middleware можно также с помощью команды:
dart_frog new middleware 'NAME_OF_FOLDER'
После добавления или изменения middleware необходимо перезапустить генерацию кода для применения изменений.
Пару важных моментов:
◽️Если файл _middleware.dart находится в папке маршрута без вложенности, middleware применяется ко всем маршрутам на этом уровне
◽️Чтобы middleware применялся только к определенным маршрутам, необходимо создать _middleware.dart внутри соответствующей папки маршрутов
◽️ Если middleware создан в произвольной, не связанной с маршрутом папке, он применен не будет
Структура middleware выглядит таким образом:
Handler middleware(Handler handler) {
return handler.use(requestLogger());
}
Кроме маршрутов и middleware, часто нужно работать с заголовками запросов. В Dart Frog это реализуется так:
Response onRequest(RequestContext context) {
final request = context.request;
final headers = request.headers; // Map<String, dynamic>
...
}
Когда вы настроили маршруты, middleware и работу с заголовками, нужно сгенерировать код маршрутов, чтобы сервер мог их использовать.
Для этого используйте:
dart_frog build
Это создает сгенерированный код маршрутов в директории build/, который используется сервером (bin/server.dart).
❗️ При работе с dart_frog важно поддерживать правильную вложенность папок, чтобы маршруты сгенерировались корректно. Более подробно можно прочитать в документации Dart Frog.
👍5❤4💩2
Привет, это Катя, Friflex Flutter Dev. Сегодня разберем TDD (Test-Driven Development) — подход к разработке, при котором сначала пишут тесты, а потом уже код.
Как это работает
▪️Пишем маленький тест, описывающий нужное поведение
▪️Запускаем его — тест падает, ведь кода еще нет
▪️Реализуем минимальный код, чтобы тест прошел
▪️Рефакторим код, при этом тесты должны оставаться зелеными
Пример для понимания
Допустим, нам нужна функция sum, которая складывает два числа.
🔴 Сначала пишем тест:
Он упадет, так как функции еще нет.
🟢Пишем минимальный код, чтобы тест прошел:
🔁 После того как тест прошел, рефакторим код
Плюсы
◽️Код становится надежнее и полностью покрыт тестами
◽️Рефакторить проще — тесты страхуют
◽️Требования становятся понятнее (каждый тест фиксирует ожидание)
Минусы
◽️Разработка стартует медленнее
◽️Нужно уметь писать хорошие тесты
◽️Сложнее применять к UI или к большим интеграциям
А как у вас с TDD?
Как это работает
▪️Пишем маленький тест, описывающий нужное поведение
▪️Запускаем его — тест падает, ведь кода еще нет
▪️Реализуем минимальный код, чтобы тест прошел
▪️Рефакторим код, при этом тесты должны оставаться зелеными
Пример для понимания
Допустим, нам нужна функция sum, которая складывает два числа.
🔴 Сначала пишем тест:
import 'package:flutter_test/flutter_test.dart';
void main() {
test('sum should return correct result', () {
expect(sum(2, 3), 5); // ожидаем 2 + 3 = 5
});
}
Он упадет, так как функции еще нет.
🟢Пишем минимальный код, чтобы тест прошел:
int sum(int a, int b) {
return a + b;
}
🔁 После того как тест прошел, рефакторим код
Плюсы
◽️Код становится надежнее и полностью покрыт тестами
◽️Рефакторить проще — тесты страхуют
◽️Требования становятся понятнее (каждый тест фиксирует ожидание)
Минусы
◽️Разработка стартует медленнее
◽️Нужно уметь писать хорошие тесты
◽️Сложнее применять к UI или к большим интеграциям
А как у вас с TDD?
🔥5❤4👍2
Media is too big
VIEW IN TELEGRAM
Разыгрываем 2 билета на CrossConf — главную конференцию по кроссплатформенным технологиям в России и СНГ.
В программе — двойной поток по Flutter от спикеров из Магнит Маркета, Лаборатории Касперского, BetBoom, Яндекс Про, Friflex и других технологичных компаний, доклады по Crossplatform и Al, нетворкинг, встреча с самой активной частью Flutter-сообщества и веселая вечеринка
Условия конкурса:
Итоги подведем 13 октября. Удачи
Please open Telegram to view this post
VIEW IN TELEGRAM
❤🔥3❤3👍1
Всем привет! Это Анна, Friflex Flutter Team Lead.
Сегодня поговорим о Pull to Refresh — популярном механизме в интерфейсах мобильных приложений, который позволяет одним жестом обновить информацию на экране.
Для пользователя это простое и понятное движение — содержимое экрана нужно потянуть сверху вниз и отпустить. В момент, когда Pull to Refresh срабатывает, пользователю показывается индикатор загрузки. Как только новые данные получены, содержимое экрана меняется, а индикатор загрузки исчезает.
Этот механизм считается неким «золотым стандартом», почти каждое коммерческое приложение не обходится без него. Почему?
▫️ Жест понятен. Пользователи уже настолько привыкли к такому поведению, что их не нужно дополнительно обучать
▫️ Процесс обновления прозрачен и нагляден. Красивые анимации, индикатор загрузки, плавные жесты — все это дает пользователю ощущение полного контроля и не вызывает вопросов
▫️ Механизм дает пользователю обновлять данные, когда он сам захочет. Это повышает его доверие и лояльность к продукту
▫️ Механизм стал настолько распространенным, что его реализация не вызывает проблем на всех платформах
Как реализовать Pull to Refresh во Flutter-приложении?
▪️Базовый виджет RefreshIndicator
Это самый простой способ. Для реализации достаточно прокручиваемый виджет на экране обернуть в RefreshIndicator, а затем добавить вызов onRefresh.
Готово! Такая реализация легко поддерживается и является стабильной.
Но тут важно учесть, что RefreshIndicator не позволит вам особенным образом кастомизировать индикатор загрузки — это всегда будет CircularProgressIndicator, который можно лишь немного видоизменить.
Также важно, что он работает только в паре с Scrollable-виджетом и может реализовать только базовый жест сверху вниз.
▪️Библиотека pull_to_refresh
Если возможностей RefreshIndicator окажется недостачно, на помощь придет SmartRefresher из библиотеки pull_to_refresh.
Этот виджет позволит не только обработать жест перезагрузки (сверху вниз), но и жест дозагрузки (снизу вверх). Можно реализовать механизм по горизонтали с помощью scrollDirection.
SmartRefresher удобен тем, что его индикатор загрузки можно кастомизировать. Пакет уже дает готовые решения, например, WaterDropHeader. С помощью CustomHeader и CustomFooter вы можете настроить вид под свои нужды.
▪️Полноценная кастомная реализация.
Если оба решения вам не подходят, и вам требуется совершенно нестандартный вид — поможет самописное решение.
Здесь перед началом разработки рекомендую оценить необходимость такого пути. Собственное решение займет очень много сил и времени, а также несет достаточно высокие риски ошибок.
Делитесь своим опытом в комментариях😘
Сегодня поговорим о Pull to Refresh — популярном механизме в интерфейсах мобильных приложений, который позволяет одним жестом обновить информацию на экране.
Для пользователя это простое и понятное движение — содержимое экрана нужно потянуть сверху вниз и отпустить. В момент, когда Pull to Refresh срабатывает, пользователю показывается индикатор загрузки. Как только новые данные получены, содержимое экрана меняется, а индикатор загрузки исчезает.
Этот механизм считается неким «золотым стандартом», почти каждое коммерческое приложение не обходится без него. Почему?
▫️ Жест понятен. Пользователи уже настолько привыкли к такому поведению, что их не нужно дополнительно обучать
▫️ Процесс обновления прозрачен и нагляден. Красивые анимации, индикатор загрузки, плавные жесты — все это дает пользователю ощущение полного контроля и не вызывает вопросов
▫️ Механизм дает пользователю обновлять данные, когда он сам захочет. Это повышает его доверие и лояльность к продукту
▫️ Механизм стал настолько распространенным, что его реализация не вызывает проблем на всех платформах
Как реализовать Pull to Refresh во Flutter-приложении?
▪️Базовый виджет RefreshIndicator
Это самый простой способ. Для реализации достаточно прокручиваемый виджет на экране обернуть в RefreshIndicator, а затем добавить вызов onRefresh.
RefreshIndicator(
onRefresh: () async {
// обновить данные тут
},
child: ListView.builder(
itemCount: items.length,
itemBuilder: (context, index) => ChildWidget(),
),
)
Готово! Такая реализация легко поддерживается и является стабильной.
Но тут важно учесть, что RefreshIndicator не позволит вам особенным образом кастомизировать индикатор загрузки — это всегда будет CircularProgressIndicator, который можно лишь немного видоизменить.
Также важно, что он работает только в паре с Scrollable-виджетом и может реализовать только базовый жест сверху вниз.
▪️Библиотека pull_to_refresh
Если возможностей RefreshIndicator окажется недостачно, на помощь придет SmartRefresher из библиотеки pull_to_refresh.
Этот виджет позволит не только обработать жест перезагрузки (сверху вниз), но и жест дозагрузки (снизу вверх). Можно реализовать механизм по горизонтали с помощью scrollDirection.
SmartRefresher(
enablePullDown: true, // включает жест сверзу вниз
enablePullUp: true, // включает жест снизу вверх
scrollDirection: Axis.vertica l// указывает направление жестов
onRefresh: _onRefresh, // обработка обновления
controller: _refreshController,
child: ListView(...),
);
SmartRefresher удобен тем, что его индикатор загрузки можно кастомизировать. Пакет уже дает готовые решения, например, WaterDropHeader. С помощью CustomHeader и CustomFooter вы можете настроить вид под свои нужды.
▪️Полноценная кастомная реализация.
Если оба решения вам не подходят, и вам требуется совершенно нестандартный вид — поможет самописное решение.
Здесь перед началом разработки рекомендую оценить необходимость такого пути. Собственное решение займет очень много сил и времени, а также несет достаточно высокие риски ошибок.
Делитесь своим опытом в комментариях
Please open Telegram to view this post
VIEW IN TELEGRAM
❤8👍5🔥2😍1😐1