Как стать автором
Обновить
4
0
Никита @nikita_dol

Flutter Dev

Отправить сообщение

Для замеров времени выполнения лучше использовать Stopwatch

То может получиться вот такой результат:

Я бы рассмотрел создание области выреза через обычный Rect (или Offset + Size если удобнее) и тогда код будет проще

В следующих статьях я рассмотрю, каким образом можно избежать как минимум потери разрешения.

Или использовать пакет image, так как аргументы против не очень сильные:

1. Да, это сторонняя зависимость, но код там не сложный, что бы повторить самому + рабочий

2. Коллизия имён - обычная проблема с простым решением

3. В основном будет преобразование во flutter что бы показать то, что вышло - что выйдет меньше чем писать свои костыли

Как итог: если добавлять более 1 шага обработки изображения, то приходим к коду как отдельный пакет image

P.S. Не говорю, что не нужно пробовать делать что-то своё, просто, иногда получается слишком много не нужного кода (например, как в статье где использовался шейдер, который родился из незнания API рисования)

  • У Matrix4 есть уже реализованные методы для разных преобразований - почему бы не использовать их?

  • У Image нужно вызывать dispose, иначе она будет вечно в памяти

  • Минус вашего подхода - потеря оригинала изображение (в следствии рисования его на канвасе) - что ведёт к ситуации, когда вырезанный фрагмент в вашем приложении не такой же, как если бы я вырезал его инструментом, предназначенным для этого

Я заметил, что качество при отрисовке картинок в CustomPainter может сильно теряться, они как бы становятся пиксельными. Заметно, когда переводишь обычную красивую картинку, например, из ассетов в ui.Image и рисуешь в пейнтере

Что если попробовать использовать FilterQuality? (его можно пробросить в drawImage через Paint.filterQuality) По идее не нужен будет шейдер

  1. Сам изолят, адаптированный для работы в вебе в том числе

В коде нету преобразования байтов обратно в модели, а используются геттеры - это добавляет некоторый оверхед на постоянную десериализацию + компилятор не может знать, что геттеры всегда возвращают одни и те же значения

разделяемой памяти нам не завезли 

А может и завезли: для изолятов -> TransferableTypedData. Для веба -> SharedArrayBuffer

лучше бы этот список сделать немодифицируемым

Для web, кстати, это не поможет

List.filled(emptyObject,growable:false)

Если и оптимизировать, то лучше использовать List.generate, так как заполнение чем-то - итерация по всем элементам

if (random.nextBool()) {
objectsSet.add(i);
}

Да, другие структуры данных быстрее, но случайное заполнение тестовых данных не делает тест объективным

Garbage Collector и испортит вам все замеры, зачищая память после предыдущего теста

Можно попробовать вызывать его между тестами и добавить немного unsafe

Можно ли написать DI библиотеку так, что бы она в debug резолвила зависимости в рантайме (как scout) , а в release во время компиляции (как dagger)?

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

Сам враппер пишется на Objective-C, но его можно использовать внутри Swift.
Например, у меня на скриншоте с кодом на Swift в 56 строке используется tryBlock из Objective-C. А сам код Objective-C со Stack Overflow. Поэтому, мы можем писать врапперы для Objective-C в Objective-C и потом использовать в Swift

Это достаточно обычная проблема, когда в Swift используется что-то из Objective-C. Если какой-то Objective-C код падает в рантайме, то можно обернуть его в другой Objective-C код, который это отловит. Тыц

Или от меня скриншот

(Промахнулся веткой, ответ на этот комментарий)

Согласно документации, drawWithCache вызывает лямбду когда изменился размер рисуемой области и/или состояние, которое читается из лямбды

В вашем случае, это сработает только между кадрами, если кадры будут рисоваться быстрее, чем вы изменяете переменную time

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

Я так понимаю, что от Modifier.drawWithCache нету смысла, так как происходит постоянное изменение времени, а значит, что шейдеры пересоздаются на каждую перерисовку

Не оправдываю svelte и не виню $mol

Но

В целом в корне дерева создаётся контейнер с помощью ProviderScope или если нужно, то создаётся ранее и потом вставляется в корень дерева с помощью UncontrolledProviderScope

Так же, обычно провайдеры создают как top-level variables, что бы они не пересоздавались.

Так же достаточно удобная возможность - использование riverpod как DI:

final httpQueryProvider = Provider(
  (ref) => HttpQuery(
    ref.watch(dioProvider),
  ),
  dependencies: [
    dioProvider,
  ],
  name: 'httpQuery',
);

class HttpQuery {
  HttpQuery(this._dio);

  final Dio _dio;

  Future<Object?> get({
    required String url,
    Map<String, Object?>? queryParameters,
    Map<String, Object?>? headerData,
  })  {
    ...
  }
}

Кстати, я пересмотрел статью ещё раз и не понял как связан LocaleNotifier и HttpQuery

.interceptors.add

Зачем добавлять новые при каждом вызове get? Лучше поместить это в dioProvider

final container = ProviderContainer();

Зачем создавать контейнер для 1 зависимости?

LocaleNotifier() : super(sharedPreference.locale) {

sharedPreference лучше брать из контейнера

Как я понял, в большинстве случаев, Intellij Idea не виновата, так как они просто подключаются к Dart Analysis Server. Порой кажется, что в команде Dart не хотят что-либо улучшать. Не хочу никого оправдывать, но выходит, что IDE виновата только от части и это не отменяет проблем описанных в статье. Я бы, например, очень хотел бы, что бы локальные переменные или функции имели приоритет в выдаче, но мечтать не вредно. тыц

Логично встает вопрос: если стандартные компоненты приходится переписывать для кастомизации под конкретные проекты, то зачем Material и Cupertino виджеты гвоздями прибиты к Flutter SDK? Не логичнее ли было вынести их как отдельные пакеты и подключать по необходимости?

Наверное, это может быть решено

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

Виджеты пересобирать - норм работает же

Самым ярким примером я бы назвал go_router ... Нестабильный API, большое количество багов, проблемный генератор роутов, сложности в вебе. И все это подается под соусом лучшего решения для Flutter — проекта

Кстати, у Flutter есть такой интересный репозиторий, где они обсуждают как реализовать те или иные вещи. И в нём можно найти как они пришли к go_router.

Не вопрос:

✓  Built build/app/outputs/flutter-apk/app-release.apk (16.8MB).

Да, это больше чем пустой проект (я создал в студии пустой проект и сделал релизный билд - 4.5Мб), но если это действительно критично, то стоит использовать только нативную разработку

Моё мнение: большинство нативных приложений уже давно имеют размер выше 15Мб - поэтому размер Flutter приложения не так критичен в большинстве случаев

К примеру пустой проект .apk ->
Flutter: 30мб+

Если запустить это в терминале:

flutter create size
cd size
flutter build apk --release --split-per-abi

То в результате сбилдятся 3 apk:

✓  Built build/app/outputs/flutter-apk/app-armeabi-v7a-release.apk (5.6MB).
✓  Built build/app/outputs/flutter-apk/app-arm64-v8a-release.apk (6.1MB).
✓  Built build/app/outputs/flutter-apk/app-x86_64-release.apk (6.2MB).

Конечно, это не 3Мб, но в 6Мб уже весь движок и кусочек приложения

Почему отказались использовать готовые пакеты?

Например, эти пакеты (первые которые попались) умеют сканить не по одному коду за раз:
https://pub.dev/packages/barcode_scan2
https://pub.dev/packages/flutter_barcode_scanner

Почему решили не использовать FileHandle для чтения файла частями?

Dart есть вспомогательная функция compute

Функция compute - часть Flutter

Важное ограничение: коллбэк ДОЛЖЕН быть функцией верхнего уровня и НЕ МОЖЕТ быть замыканием или методом класса (даже статическим).

C версии 2.15 это предложение не соответствует действительности

Другими словами, платформенные взаимодействия невозможны в экземплярах Isolate, создаваемых вами программно.

Кстати, есть способы обойти это

на самом деле под капотом 4 потока

Почему не 5?

Левое приложение - PWA. Правое - из маркета
Левое приложение - PWA. Правое - из маркета

Так же, сборка из маркета сбрасывает настройки ленты (язык, стиль, язык интерфейса) если перейти на вторую страницу в ленте. (только установил приложение и не залогинился)

Информация

В рейтинге
Не участвует
Откуда
Гродно, Гродненская обл., Беларусь
Зарегистрирован
Активность