Flutter Pulse
497 subscribers
302 photos
635 links
На канале будут новости про flutter с сайтов, информация об обновлении пакетов, а также авторский контент.
Download Telegram
🚀 Погружаемся в мир статического анализа Flutter: как сделать код идеальным?

Привет, Flutter-энтузиасты! 👋 Только что наткнулся на 🔥горячее видео от Кости Фидурова (Flutter-разработчик Яндекс Pro), которое перевернёт ваше представление о качестве кода! Если вы хоть раз задумывались о:

🔧 Настройке анализатора
✍️ Создании своих lint-правил
🚫 Борьбе с "ворнингами" в проектах

— это must-watch! 💡

👉 О чём видео?
Костя детально разбирает работу статического анализа в Dart:
Чем анализатор отличается от линтера
Как настроить analysis_options.yaml под свои нужды
Секреты кастомизации правил (даже написали плагин для префикса my_ в реальном времени!)
Практические примеры дебага AST (синтаксических деревьев)

💎 Самые сочные моменты:
Разбор 4 ключевых компонентов анализа: код, анализатор, конфиг, analysis server
Как избежать runtime-ошибок через strict-casts
Создание кастомного линт-правила за 40 строк кода!
Фикс типичных ошибок через Quick Fix в IDE

🔗 Смотрите запись лекции:
Анализатор — ШМР Flutter 2025

💬 "Приготовьтесь сделать ваш код чище и профессиональнее!" — обещаю, после просмотра вы:
• Пересмотрите настройки линтинга в своих проектах
• Научитесь ловить баги до запуска приложения
• Сможете создавать правила под специфику команды

👉 Не пропустите! Это глоток свежего воздуха для всех, кто устал от бесконечных ignore: todo в коде.

📌 Подписывайтесь на наш канал, чтобы первыми получать лучшие Flutter-материалы! Ищите другие сокровища по хэштегу: #FlutterPulseYoutube

#Flutter #Dart #FlutterPulse #FlutterPulseTips #FlutterPulseYoutube
Имитация вызовов REST API
Привет, разработчики Flutter! 👋 Сегодня мы рассмотрим важный аспект тестирования приложений — имитацию вызовов REST API. 📱💻

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

Как это работает?
1. Импортируйте пакет mocktail:
import 'package:mocktail/mocktail.dart';


2. Создайте класс HttpClientMock, который имитирует поведение HttpClient:
class HttpClientMock extends Mock implements HttpClient {}
final httpClientMock = HttpClientMock();


3. Используйте when для определения поведения имитированного клиента:
when(() => httpClientMock
.get(Uri.parse('myapi/...')))
.thenAnswer((_) async => Response('''
{"id":"testId","route":"myPage"}
''', 200));


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

Оцените нашу новую рубрику и оставьте свои комментарии! 💬

Все подобные новости можно найти по хэштегу #FlutterPulseTips
#flutter #dart #flutterpulse #FlutterPulseTips #MobileAppDevelopment #AppTesting #MockingAPI #FlutterTips
👍5
Расширение цвета из шестнадцатеричной строки
Привет, разработчики Flutter! 👋 Сегодня мы рассмотрим полезный совет, который упростит работу с цветами в ваших приложениях. 🌈

Проблема: Часто цвета в приложениях представлены в виде шестнадцатеричных строк (например, "#FFFFFF" или "FF0000"). Но как легко преобразовать эти строки в объекты Color, с которыми можно работать в Flutter? 🤔

Решение: Мы создадим расширение для класса Color, которое позволит легко конвертировать шестнадцатеричные строки в цвета. 💡


extension HexColor on Color {
static Color fromHex(String hexString) {
final buffer = StringBuffer(); // Создаем буфер для формирования итоговой строки
if (hexString.length == 6 || hexString.length == 7) // Проверяем длину строки
buffer.write('ff'); // Если длина 6 или 7, добавляем 'ff' (полная непрозрачность)
buffer.write(hexString.replaceFirst('#', '')); // Удаляем символ '#' из строки
return Color(int.parse(buffer.toString(), radix: 16)); // Преобразуем строку в число и создаем цвет
}
}


Как это работает:
1. Мы проверяем длину строки: если она 6 или 7 символов, добавляем 'ff' для полной непрозрачности.
2. Удаляем символ '#' из строки, если он есть.
3. Преобразуем полученную строку в число в шестнадцатеричной системе и создаем объект Color.

Теперь вы можете легко использовать шестнадцатеричные строки для создания цветов в вашем приложении Flutter! 🎉

Оцените нашу новую рубрику и оставьте свои комментарии! 💬 Все подобные новости вы можете найти по хэштегу #FlutterPulseTips. 👍

#flutter #dart #flutterpulse #FlutterPulseTips #MobileDev #AppDevelopment #CodingTips #ColorUtils
👍2
Триггер событий при навигации по страницам с помощью Flutter RouteObserver

Привет, разработчики Flutter! 👋 Сегодня мы рассмотрим полезный совет по использованию RouteObserver для отслеживания навигации между страницами в вашем приложении. 📱

Что такое RouteObserver?
`RouteObserver` - это класс, позволяющий отслеживать изменения маршрутов в вашем приложении. Он предоставляет методы для реакции на различные события навигации, такие как открытие новой страницы или возврат к предыдущей. 🔄

Пример использования:
Чтобы использовать `RouteObserver`, вам нужно создать экземпляр класса, наследующего от `RouteObserver<PageRoute<dynamic>>`, и переопределить нужные методы. Ниже приведён пример кода:



class MyNavigatorObserver extends RouteObserver<PageRoute<dynamic>> {
@override
void didPush(Route<dynamic> route, Route<dynamic>? previousRoute) {
// Код, выполняемый при открытии новой страницы
}

@override
void didReplace({Route<dynamic>? newRoute, Route<dynamic>? oldRoute}) {
// Код, выполняемый при замене маршрута
}

@override
void didPop(Route<dynamic> route, Route<dynamic>? previousRoute) {
// Код, выполняемый при закрытии текущей страницы
}
}



Затем добавьте этот наблюдатель в ваше `MaterialApp`:



class MyApp extends StatelessWidget {
final _navigatorKey = GlobalKey<NavigatorState>();
final navObserver = MyNavigatorObserver();

@override
Widget build(BuildContext context) =>
MaterialApp(
navigatorObservers: [navObserver],
// Другие свойства MaterialApp
);
}



Зачем это нужно?
Использование `RouteObserver` позволяет легко отслеживать события навигации, что может быть полезно для аналитики, логирования или выполнения определённых действий при переходе между экранами. 📊🔍

Оцените новую рубрику и напишите в комментариях, насколько она вам полезна! 👍💬
Все подобные новости вы можете найти по хэштегу #FlutterPulseTips

#flutter #dart #flutterpulse #FlutterPulseTips #MobileDev #AppDevelopment #CodingTips #FlutterTips
👍3
Flutter советы - Как связать анимации в цепочку

Привет, разработчики Flutter! 👋 Сегодня мы поделимся с вами полезным советом о том, как создавать сложные анимации, связывая их в цепочку с помощью одного контроллера анимации 🔄

Создание сложных анимаций
Вы можете создать сложные анимации, связывая несколько анимаций в одну цепочку с помощью AnimationController. Это позволяет вам управлять несколькими анимациями одновременно и создавать более интересные и динамичные пользовательские интерфейсы 🎨



fadeAnimController = AnimationController(
vsync: this,
duration: Duration(milliseconds: 2000));
backgroundAnimation = CurvedAnimation(
parent: fadeAnimController,
curve: Interval(0, .4, curve: Curves.easeIn));
titleOpacityAnimation = CurvedAnimation(
parent: fadeAnimController,
curve: Interval(.4, .5, curve: Curves.easeIn));
titleSizeAnimation = CurvedAnimation(
parent: fadeAnimController,
curve: Interval(.4, .6, curve: Curves.easeInOutBack));
// ... свяжите другие анимации



В этом примере мы создаем AnimationController с длительностью 2 секунды и три CurvedAnimation, которые привязаны к этому контроллеру. Каждая CurvedAnimation имеет свой собственный интервал и кривую, что позволяет нам создавать сложные анимации 🔩

Оцените новую рубрику и оставьте свои комментарии! 💬

Все подобные новости можно найти по хэштегу #FlutterPulseTips

#flutter #dart #flutterpulse #FlutterPulseTips #AnimationTips #UIUX #MobileDevelopment #FlutterTips
👍3
Тестирование выбрасывания ошибки
Привет, Flutter-разработчики! 🤖💻
Сегодня мы рассмотрим полезный совет по тестированию в Flutter: как проверить, что ваше приложение выбрасывает конкретную ошибку. Это очень важно для обеспечения стабильности и надежности вашего приложения. 📈

Вы когда-нибудь сталкивались с ситуацией, когда ваш код выбрасывает ошибку, и вы не знали, как ее правильно протестировать? 🤔 Теперь у вас есть решение! Мы будем использовать `testWidgets` для проверки того, что виджет выбрасывает ожидаемую ошибку.

Пример кода:


testWidgets('создание виджета с некоторым параметром → throw', (WidgetTester tester) async {
var exceptionRes;
// catch flutter error или это приведет к провалу теста
FlutterError.onError = (details) {
exceptionRes = details.exception;
};
await tester.pumpWidget(myAppWithError);
// вернуть обработчик ошибок Flutter обратно
// Flutter выбросит ошибку, если этого не сделать
FlutterError.onError = (details) => FlutterError.presentError(details);
expect(exceptionRes, isNotNull);
expect(exceptionRes, isInstanceOf<MyCustomException>());
});



В этом примере мы тестируем, что виджет выбрасывает `MyCustomException`, когда ему передаются определенные параметры. Мы используем `FlutterError.onError` для перехвата исключения и его проверки.

Оцените нашу новую рубрику и напишите в комментариях, какие темы вы хотели бы видеть в будущем! 💬

Все подобные новости можно найти по хэштегу #FlutterPulseTips. 🔍
#flutter #dart #flutterpulse #FlutterPulseTips #MobileDevelopment #FlutterTips #Programming #SoftwareDevelopment #ErrorHandling #Testing
Отслеживание жизненного цикла приложения
Привет, подписчики! 👋 Сегодня мы рассмотрим очень полезный совет по Flutter - отслеживание жизненного цикла приложения. 📱💻

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

В примере кода ниже показано, как это работает:


class CameraAwesomeState extends State<CameraAwesome> with WidgetsBindingObserver {
// ...
@override
void didChangeAppLifecycleState(AppLifecycleState state) {
super.didChangeAppLifecycleState(state);
switch (state) {
case AppLifecycleState.resumed:
if (!started) {
CamerawesomePlugin.start(); // Запуск камеры при возобновлении работы приложения
}
break;
case AppLifecycleState.inactive:
case AppLifecycleState.paused:
case AppLifecycleState.detached:
if (started) {
CamerawesomePlugin.stop(); // Остановка камеры при переходе в фон или закрытии приложения
}
break;
}
}
// ...
}



Жизненный цикл приложения включает четыре основных состояния:
- resumed - приложение активно и видимо для пользователя.
- inactive - приложение не активно, но ещё видимо.
- paused - приложение не активно и не видимо (находится в фоне).
- detached - приложение закрыто.

Используя эти знания, вы сможете лучше управлять ресурсами вашего приложения и улучшать пользовательский опыт! 🌟

Оцените новую рубрику и напишите в комментариях, что вы думаете о ней! 💬

Все подобные новости можно найти по хэштегу #FlutterPulseTips. 🔍
#flutter #dart #flutterpulse #FlutterPulseTips #MobileDev #AppDevelopment #ProgrammingTips #TechNews
👍5
Предоставление разрешений в интеграционных тестах на Android с помощью командной строки adb

Привет, разработчики Flutter! 👋 Сегодня мы поделимся с вами полезным советом о том, как предоставлять разрешения в интеграционных тестах на Android с помощью командной строки adb. 📱💻

Зачем это нужно?
При выполнении интеграционных тестов на Android ваше приложение может требовать определённые разрешения. Без этих разрешений тесты могут завершиться неудачей. 🤕

Решение
Используйте команду adb для предоставления разрешений вашему приложению перед выполнением тестов. Вот пример кода на Dart, который демонстрирует, как это можно сделать:



const List<String> permissions = [
'android.permission.WRITE_EXTERNAL_STORAGE', // Разрешение на запись во внешнее хранилище
'android.permission.RECORD_AUDIO', // Разрешение на запись аудио
];

const String _examplePackage = 'com.apparence.example'; // Имя пакета вашего приложения

Future<void> main() async {
// Предоставляем разрешения перед запуском тестов
permissions.forEach((permission) => Process.runSync(
'adb', ['shell', 'pm', 'grant', _examplePackage, permission]));

print('Starting test.'); // Начало теста
await integrationDriver(); // Запуск интеграционных тестов
print('Test finished. Revoking permissions...'); // Окончание теста и отзыв разрешений

// Отзываем разрешения после завершения тестов
permissions.forEach((permission) => Process.runSync(
'adb', ['shell', 'pm', 'revoke', _examplePackage, permission]));
}



Этот код сначала предоставляет необходимые разрешения, затем запускает интеграционные тесты, и, наконец, отзывает разрешения после завершения тестов. 🔄

Оцените нашу новую рубрику советов для Flutter-разработчиков! 👍 Ваши отзывы помогут нам сделать её ещё лучше. 💬

Все подобные новости вы можете найти по хэштегу #FlutterPulseTips

#flutter #dart #flutterpulse #FlutterPulseTips #MobileDev #AndroidDev #IntegrationTesting #FlutterTips
👍2
Изменение модели родительского виджета из дочернего
с использованием виджета Actions и модели Intent 🤯

Привет, разработчики Flutter! 👋 Сегодня мы рассмотрим интересный трюк, который поможет вам изменить модель родительского виджета из дочернего компонента. Это очень полезный навык при создании сложных интерфейсов. 📱

Основная идея
Используем виджет Actions и модель Intent для взаимодействия между родительским и дочерним компонентами.

Пример кода


// Используем intent для изменения модели действия
class AppBarBuildIntent extends Intent {
final PreferredSizeWidget? appbar;
AppBarBuildIntent(this.appbar);
}

// Действие, которое можно вызвать из любого дочернего элемента
class BartAppbarAction extends Action<AppBarBuildIntent> {
final ValueNotifier<PreferredSizeWidget?> appbar;
BartAppbarAction(this.appbar);

@override
void invoke(covariant AppBarBuildIntent intent) {
this.appbar.value = intent.appbar;
}
}

class MyWidget extends StatelessWidget {
final ValueNotifier<PreferredSizeWidget?> appBarNotifier = ValueNotifier(null);

MyWidget({Key? key}) : super(key: key);

@override
Widget build(BuildContext context) {
return Actions(
actions: <Type, Action<Intent>>{
AppBarBuildIntent: BartAppbarAction(appBarNotifier),
},
child: AnimatedBuilder(
animation: appBarNotifier,
builder: (ctx, child) => ...,
),
);
}
}

// Вызов в дочернем элементе для изменения родителя (appBar)
Actions.invoke(context, AppBarBuildIntent(AppBar(title: Text("title text"))));



Этот подход позволяет элегантно управлять состоянием родительского виджета из дочерних компонентов. 👍

Оцените новую рубрику FlutterPulseTips! 😊 Нам важно ваше мнение!

Все подобные новости вы можете найти по хэштегу #FlutterPulseTips

#flutter #dart #flutterpulse #FlutterPulseTips #MobileDev #WidgetMagic #StateManagement #FlutterTips
Отслеживание изменений размера окна

Привет, Flutter-разработчики! 👋 Сегодня мы поделимся с вами полезным советом о том, как отслеживать изменения размера окна в вашем приложении Flutter 🌟

Используем WidgetBindingObserver

Для того чтобы отслеживать изменения размера окна, мы будем использовать `WidgetBindingObserver`. Этот миксин позволяет нам получать уведомления о различных событиях, происходящих в приложении, включая изменения размера окна 📱

Пример кода



class MetricsReactor extends StatefulWidget {
const MetricsReactor({Key? key}) : super(key: key);

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

class _MetricsReactorState extends State<MetricsReactor> with WidgetsBindingObserver {
late Size _lastSize;

WidgetsBinding get widgetBinding => WidgetsBinding.instance!;

@override
void initState() {
super.initState();
_lastSize = WidgetsBinding.instance!.window.physicalSize;
widgetBinding.addObserver(this);
}

@override
void dispose() {
widgetBinding.removeObserver(this);
super.dispose();
}

@override
void didChangeMetrics() {
setState(() {
_lastSize = widgetBinding.window.physicalSize;
});
}

@override
Widget build(BuildContext context) {
return Text('Текущий размер: $_lastSize');
}
}



В этом примере мы создаем `StatefulWidget` под названием `MetricsReactor`, который использует `WidgetsBindingObserver` для отслеживания изменений размера окна. Когда размер окна изменяется, мы обновляем состояние виджета с новым размером 📈

Оцените нашу новую рубрику! 👍 Мы надеемся, что вам понравится эта рубрика и вы найдете ее полезной. Оцените нас и подпишитесь на наш канал, чтобы быть в курсе всех последних советов и новостей из мира Flutter 📲

Все подобные новости можно найти по хэштегу #FlutterPulseTips

#flutter #dart #flutterpulse #FlutterPulseTips #MobileDevelopment #FlutterTips #Programming #Development #Coding
👍2
6 способов копирования списков и карт в Dart

Привет, разработчики Flutter! 👋

В Dart существует несколько способов копирования списков и карт. Давайте рассмотрим шесть наиболее популярных методов:

1. Использование json decode/encode - клонирование без сохранения ссылки

   List newList = json.decode(json.encode(oldList));
Map newMap = json.decode(json.encode(oldMap));


2. Использование оператора spread - клонирование без сохранения ссылки

   List newList = [...oldList];
Map newMap = {...oldMap};
HashMap newMap = HashMap.from({...oldMap});


3. Использование фабрики from - копирование ссылки на значение

   List newList = List.from(oldList);
Map newMap = Map.from(oldMap);


4. Использование метода addAll - копирование ссылки на значение

   List newList = []..addAll(oldList);


5. Использование пакета built_collection - не создает копию, а возвращает обертку с возможностью записи при изменении

   var builtList = [1, 2, 3].build();
builtList = builtList.rebuild((b) => b..addAll([7, 6, 5]));


6. Использование пакета fast_immutable_collections

   final IList<String> oldList;
var newList = IList.orNull(oldList);


Эти методы помогут вам эффективно работать со списками и картами в Dart. 👍

Оцените нашу новую рубрику и напишите в комментариях, что хотите видеть в следующих постах! 💬

Все подобные новости можно найти по хэштегу #FlutterPulseTips

#flutter #dart #flutterpulse #FlutterPulseTips #codingtips #mobiledevelopment #programming #FlutterTips #DartLang
Flutter советы - Как обрезать изображение

Привет, разработчики! 👋 Сегодня мы рассмотрим простой, но полезный совет по Flutter - обрезку изображений! 📸✂️

Вы когда-нибудь сталкивались с необходимостью обрезать изображение в вашем приложении Flutter? 🤔 Это может быть полезно для создания миниатюр, улучшения композиции или просто для придания приложению более аккуратного вида. 💁‍♀️

Решение: Используйте виджет ClipRect! 🎉



Container(
alignment: Alignment.topCenter,
child: ClipRect(
child: Image.asset(
'assets/04.jpg', // Путь к изображению
width: 400, // Ширина изображения
height: 400, // Высота изображения
fit: BoxFit.none, // Не масштабировать изображение
alignment: Alignment.topCenter, // Выравнивание по верхнему центру
),
),
)



В этом примере мы используем виджет Container с выравниванием по верхнему центру. Внутри контейнера мы размещаем виджет ClipRect, который обрезает изображение до указанного размера. Изображение загружается из assets с помощью виджета Image.asset. Мы устанавливаем ширину и высоту изображения в 400 пикселей и отключаем масштабирование с помощью BoxFit.none. Выравнивание изображения также установлено по верхнему центру.

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

Оцените нашу новую рубрику и оставьте свои комментарии! 💬 Понравился ли вам этот совет?👍

Все подобные новости можно найти по хэштегу #FlutterPulseTips

#flutter #dart #flutterpulse #FlutterPulseTips #MobileDevelopment #AppDevelopment #UIUX #CodingTips #ImageCropping #FlutterTips