Так Android и Jetpack Compose, который упоминается в статье, тоже made by Google и по той же логике точно также могут быть закрыты. Можно, конечно, допустить, что неожиданно Flutter решат закрыть через какое-то время, но объективных причин для этого нет. Сам SDK развивается, количество вакансий и разработчиков растет, есть поддержка Fuchsia (если она когда-нибудь разовьётся во что-нибудь для мобилок).
Вот, например, давайте посмотрим на Dart: когда в него завезли null safety? Правильно, только весной 2021 года, а ведь это базовый механизм статической типизации.
Нет такого общепринятого понятия, как "базовый механизм статической типизации" для null safety. Просто в Kotlin/Swift это появилось уже после того, как вышел Dart. Да и сама фича достаточно сложная для добавления, потому что требует правки всей системы типов, миграции кода библиотек/приложений. Если сравнивать с Kotlin, то в итоге получилось даже лучше, потому что компилятор Dart может использовать информацию о типах и вырезать проверки на null в нативном коде, что повышает производительность и уменьшает размер сборки, а в Kotlin это все остается на границах публичных методов, потому что рантайм ничего не знает об этом. В Dart'e действительно нет многих фишек современных языков, но если смотреть не в моменте, а за период с релиза Flutter то развивается он достаточно бодро и разрабы прислушиваются к коммьюнити. Плюс у Dart'a тут есть возможность насобирать шишек за чужой счет и добавлять фичи более обдуманно. Да, конечно, хочется все и сразу, но развитие есть.
Конечно, прекрасно, что Flutter можно посмотреть в исходниках, как и увидеть, сколько issues сейчас открыто в официальном репозитории: их количество только растёт — это говорит о том, что команда пока не справляется с потоком ошибок. Например, только совсем недавно сделали, чтобы анимации не тормозили на iOS ¯_(ツ)_/¯
Количество isssues не равно количеству ошибок, потому что это могут быть фича реквесты, вопросы по использованию SDK, инфраструктурные проблемы, ошибки в desktop платформах (которые еще не в релизе), да и вообще что угодно. Количество тасок скорее говорит о том, что само сообщество вокруг Flutter большое и растет.
По поводу проблем с анимациями на iOS: такая проблема действительно была, но по статье не понятно, аффектило ли это вас или это просто пример. Когда мы выпускали приложение (которое уже было в сторе на Android) на iOS то таких проблем не было.
Собственный UI, характерный для обеих мобильных платформ
Поведение на разных платформах можно кастомизировать, часть из этого работает уже по умолчанию. В примерах есть приложение, которое на разных платформах выглядит нативно при этом максимально переиспользует общие части. Могут быть и другие варианты как это решить, все зависит от дизайна и требований. Тут действительно можно упрекнуть Flutter в том, что он не может как-то автоматически менять UI на разных платформах, чтобы приложение выглядело нативно, но UI паттерны могут отличаться слишком сильно.
В целом доводы в статье субъективные и эмоциональные, а при таком серьезом решении о миграции всего приложения на другой стек, выглядит как раз необдуманно, но, с другой стороны, дает понимание о подходах в компании к таким вопросам.
По поводу Сбертеха. Не скажу за весь, но во многих проектах абсолютно такая же ситуация как описано в статье про «махровый авторитаризм». Новые технологии или идеи высмеиваются, люди которые их предлагают подвергаются натуральной травле в переписках, презентациях, чатах. Это не шутки. Про это тоже у автора было. Понятно, что технологии, ради технологий это не серьезно, особенно учитывая специфику банковских приложений. Но даже объективные факты в виде повышения качества и стабильности приложений не играют никакой роли.
И?
В текущей ситуации, вам кажется что код выше, т.е.:
class BadDouble: Foo<kotlin.Double> {
override fun bar(vararg a: kotlin.Double) {
throw UnsupportedOperationException()
}
}
Должен скомпилироваться в:
public final class BadDouble implements Foo<double>
{
public void bar(double... a)
{
throw ((Throwable)new UnsupportedOperationException("not implemented"));
}
}
Но такая конструкция в текущей версии Java просто не поддерживается, как это уже писал выше.
Какие есть варианты решения проблемы?
1. (как сейчас) выдавать ошибку компиляции
2. не явно преобразовывать Integer[] и вставлять хаки при конвертации между int[] и bar(vararg a: kotlin.Double).
Причем тут дизайн языка, да и vararg вообще, проблема как раз в самой платформе: в Java в принципе нельзя сделать метод с примитивом в качестве generic параметра, что вы и пытаетесь осуществить. Попробуйте переписать пример выше на обычной джаве и скормить там в качестве параметра типа обычный int — на текущей версии Java так сделать нельзя, почему это происходит кидал ссылку в статье про боксинг.
Так и Котлин не может kotlin.Double сконвертить в int для дженериков, поскольку сами дженерики и там и там практически идентичны. Да, он может это не пишет явно в сообщение об ошибке, но тут догадаться и так можно почему это происходит.
Чтобы исправить данный пример можно отметить в самом дженерике тип как kotlin.Double? тогда все будет успешно. Или просто убрать дженерики вообще и написать:
fun bar(vararg a: Double) {
throw UnsupportedOperationException("not implemented")
}
тогда он сгенерит:
public final void bar(double... a) {
throw (Throwable)(new UnsupportedOperationException("not implemented"));
}
Мне кажется достаточно трудно делать какие-то выводы об оптимизациях на уровне JVM в данном случае без отрыва от тестов. Вообще зачем действительно там nop мне трудно сказать, могу лишь предположить, что возможно это как-то связано с дебагом.
Естественно нет, он не будет за вас создавать синхронизацию и прочее. Для большинства случаев это просто не нужно, например если null переменная объявляется внутри метода.
inline все же в scala есть считай из «коробки», а вместо reified type есть TypeTag (если не путаю) с большим функционалом.
Все же разница там есть, если вы говорите про аннотацию inline, то мне кажется текущая версия комплятора скалы не сможет так развернуть лямбды, как это делает котлин, например, для всех функций работы с коллекциями. Если же речь о макросах, то тут у скалы возможности не ограничены, но использовать их сложней. reified type parameters связаны как раз именно с инлайном, поэтому у скалы вероятно тут прямого аналога нет, а TypeTag это вообще вроде как фича из рефлекшена, разве нет?
Вряд ли какая-то статья даст вам конкретный ответ на этот вопрос, пока сами не попробуете.
В сравнение со скалой, вероятно, переходить особого смысла и нет. Хотя если говорить еще про отличия и плюсы, то в статье не упомянули про инлайн функций и reified type parameters. На скале такое сделать значительно трудней. Очень радует маленький рантайм самого языка, особенно это удобно на андроиде, на скале с этим пока не так весело, но работы там вроде как ведутся. Еще в котлине заморочились c примитивами и их массивами, массивы также поддерживают все операции работы с коллекциями (map, find...), причем реализованы они не через ссылочные типы, т.е. боксинга/анбокисинга не будет, если конечно результат потом как-то не явно будет приведен к ссылочному типу, например, объявлен как nullable.
Из минусов:
— плагин для идеи периодически крашится, не критично, но хочется чтобы его довели до уровня;
— странный синтаксис в некоторых местах, например при объявлении свойств и если вдруг захочется добавить аннотацию к конструктору, то придется явно это указать;
Ну да, в случае смены конфигурации лоадер тот же, а если все уходит в background то прибивается вместе с ui, если нужно чтобы такого не было то IntentService в помощь (ну или обычный сервис). Если же речь идет о запросах то тут volley классный врапер. В любом случае они используют статические переменные для хранения результата, так что чем-то похоже на вашу реализацию.
Ну и что? execute у AsyncBean тоже 2 раза нужно будет вызывать. С id проблему не вижу, ну есть он и есть, внутри отдельного фрагмента коллизия не возникнет :)
Кажется понял, для AsyncBean идентификаторы должны быть уникальны для всего приложения, поскольку они хранятся как статическое поле, а для лоадеров они уникальны только в пределах LoaderManager'a, который привязан к фрагменту или активити. Поэтому там все проще.
На счет Bundle'ов согласен с вами, действительно многобукоф, неудобно.
Не вижу в чем проблема с AsyncTaskLoader. Id будет хранится как обычная константа, этот идентификатор как раз определяет какая из задач сейчас выполняется. Сериализовывать тоже ничего не надо, зачем? Результат будет хранится в самом лоадере.
Честно говоря не понял зачем нужная такая сложная логика внутри UidGenerator для генерации айдишников AsyncBean. Но там кстати используются интерфейс Application.ActivityLifecycleCallbacks доступный только с 14 версии, а те же Loaders доступны в support-library v4.
Flutter vs Native: почему мы переходим с первого на второй
Так Android и Jetpack Compose, который упоминается в статье, тоже made by Google и по той же логике точно также могут быть закрыты. Можно, конечно, допустить, что неожиданно Flutter решат закрыть через какое-то время, но объективных причин для этого нет. Сам SDK развивается, количество вакансий и разработчиков растет, есть поддержка Fuchsia (если она когда-нибудь разовьётся во что-нибудь для мобилок).
Нет такого общепринятого понятия, как "базовый механизм статической типизации" для null safety. Просто в Kotlin/Swift это появилось уже после того, как вышел Dart. Да и сама фича достаточно сложная для добавления, потому что требует правки всей системы типов, миграции кода библиотек/приложений. Если сравнивать с Kotlin, то в итоге получилось даже лучше, потому что компилятор Dart может использовать информацию о типах и вырезать проверки на null в нативном коде, что повышает производительность и уменьшает размер сборки, а в Kotlin это все остается на границах публичных методов, потому что рантайм ничего не знает об этом. В Dart'e действительно нет многих фишек современных языков, но если смотреть не в моменте, а за период с релиза Flutter то развивается он достаточно бодро и разрабы прислушиваются к коммьюнити. Плюс у Dart'a тут есть возможность насобирать шишек за чужой счет и добавлять фичи более обдуманно. Да, конечно, хочется все и сразу, но развитие есть.
Количество isssues не равно количеству ошибок, потому что это могут быть фича реквесты, вопросы по использованию SDK, инфраструктурные проблемы, ошибки в desktop платформах (которые еще не в релизе), да и вообще что угодно. Количество тасок скорее говорит о том, что само сообщество вокруг Flutter большое и растет.
По поводу проблем с анимациями на iOS: такая проблема действительно была, но по статье не понятно, аффектило ли это вас или это просто пример. Когда мы выпускали приложение (которое уже было в сторе на Android) на iOS то таких проблем не было.
Поведение на разных платформах можно кастомизировать, часть из этого работает уже по умолчанию. В примерах есть приложение, которое на разных платформах выглядит нативно при этом максимально переиспользует общие части. Могут быть и другие варианты как это решить, все зависит от дизайна и требований. Тут действительно можно упрекнуть Flutter в том, что он не может как-то автоматически менять UI на разных платформах, чтобы приложение выглядело нативно, но UI паттерны могут отличаться слишком сильно.
В целом доводы в статье субъективные и эмоциональные, а при таком серьезом решении о миграции всего приложения на другой стек, выглядит как раз необдуманно, но, с другой стороны, дает понимание о подходах в компании к таким вопросам.
Первый байндинг для Exonum: почему мы выбрали Java
Про рынок ИТ в России по-честному
Про рынок ИТ в России по-честному
Kotlin и autoboxing
В текущей ситуации, вам кажется что код выше, т.е.:
Должен скомпилироваться в:
Но такая конструкция в текущей версии Java просто не поддерживается, как это уже писал выше.
Какие есть варианты решения проблемы?
1. (как сейчас) выдавать ошибку компиляции
2. не явно преобразовывать Integer[] и вставлять хаки при конвертации между int[] и bar(vararg a: kotlin.Double).
Kotlin и autoboxing
kotlin.Double? — выделил важное жирным
Не знаю откуда вы это взяли вообще.
Читайте внимательней комментарий к таску, там как раз все развернуто описано.
Kotlin и autoboxing
Так и Котлин не может kotlin.Double сконвертить в int для дженериков, поскольку сами дженерики и там и там практически идентичны. Да, он может это не пишет явно в сообщение об ошибке, но тут догадаться и так можно почему это происходит.
Чтобы исправить данный пример можно отметить в самом дженерике тип как kotlin.Double? тогда все будет успешно. Или просто убрать дженерики вообще и написать:
тогда он сгенерит:
что вероятно и хотелось изначально.
Kotlin и autoboxing
Kotlin и autoboxing
Kotlin и autoboxing
Scala vs Kotlin (перевод)
Все же разница там есть, если вы говорите про аннотацию inline, то мне кажется текущая версия комплятора скалы не сможет так развернуть лямбды, как это делает котлин, например, для всех функций работы с коллекциями. Если же речь о макросах, то тут у скалы возможности не ограничены, но использовать их сложней. reified type parameters связаны как раз именно с инлайном, поэтому у скалы вероятно тут прямого аналога нет, а TypeTag это вообще вроде как фича из рефлекшена, разве нет?
А так полностью согласен.
Scala vs Kotlin (перевод)
В сравнение со скалой, вероятно, переходить особого смысла и нет. Хотя если говорить еще про отличия и плюсы, то в статье не упомянули про инлайн функций и reified type parameters. На скале такое сделать значительно трудней. Очень радует маленький рантайм самого языка, особенно это удобно на андроиде, на скале с этим пока не так весело, но работы там вроде как ведутся. Еще в котлине заморочились c примитивами и их массивами, массивы также поддерживают все операции работы с коллекциями (map, find...), причем реализованы они не через ссылочные типы, т.е. боксинга/анбокисинга не будет, если конечно результат потом как-то не явно будет приведен к ссылочному типу, например, объявлен как nullable.
Из минусов:
— плагин для идеи периодически крашится, не критично, но хочется чтобы его довели до уровня;
— странный синтаксис в некоторых местах, например при объявлении свойств и если вдруг захочется добавить аннотацию к конструктору, то придется явно это указать;
Сбербанк делится опытом создания приложения в Material Design: стили и темы
AppCompat v21 — Material Design для пре-Lollipop устройств
AppCompat v21 — Material Design для пре-Lollipop устройств
Как не потерять связь между фоновыми задачами и Activity
Как не потерять связь между фоновыми задачами и Activity
Как не потерять связь между фоновыми задачами и Activity
или
разницы никакой, только в случае AsyncBean нужно еще обработать onSaveInstanceState/onPause/onResume, проверить savedInstanceState.
Как не потерять связь между фоновыми задачами и Activity
Как не потерять связь между фоновыми задачами и Activity
Не вижу в чем проблема с AsyncTaskLoader. Id будет хранится как обычная константа, этот идентификатор как раз определяет какая из задач сейчас выполняется. Сериализовывать тоже ничего не надо, зачем? Результат будет хранится в самом лоадере.
Честно говоря не понял зачем нужная такая сложная логика внутри UidGenerator для генерации айдишников AsyncBean. Но там кстати используются интерфейс Application.ActivityLifecycleCallbacks доступный только с 14 версии, а те же Loaders доступны в support-library v4.