#НоваяАватарка #АвторНедели
Доброй ночи, друзья!
Меня зовут Даниил Попов и я перенимаю эстафету у Николая - на этой… twitter.com/i/web/status/1…
Коротко обо мне. Я Android team lead в компании @mailru, работаю в юните Instant Messengers. Веду авторский курс по… twitter.com/i/web/status/1…
План на неделю у меня следующий:
День 1: Образование
День 2: Кроссплатформа (в основном боль)
День 3: Как заставить… twitter.com/i/web/status/1…
У меня есть план и я буду его придерживаться, но вопросы можно накидывать уже сейчас.
День 1. Образование.
Всем доброго утра (во всяком случае по Москве)! Сегодня мы поговорим про образование для мобил… twitter.com/i/web/status/1…
Зачем вообще нужны образовательные проекты IT-компании? В данный момент у Mail.ru 7 образовательных… twitter.com/i/web/status/1…
Нередко для компании выходит дешевле довести стажёра до условного миддла, чем взять готового с улицы. Поэтому таког… twitter.com/i/web/status/1…
@mobileunderhood А диплом хоть как-то ценится или это сейчас рудимент? Как считаешь?
Для меня наличие базовых знаний куда важнее, чем наличие картонки с оценками. Но при этом свою базу и основы я полу… twitter.com/i/web/status/1…
Программа в Технопарке называется "Системный архитектор", мобильная разработка (а есть курс и по iOS) лишь один из… twitter.com/i/web/status/1…
Курс базовый и содержит самые основы. Основная идея в том, чтобы после курса студенты могли сделать несложное клиен… twitter.com/i/web/status/1…
Мобильная разработка это easy to learn, hard to master. То есть делать приложения можно уже через пару недель экспе… twitter.com/i/web/status/1…
С одной стороны наличие всяких Jetpack'ов помогает быстрее начать и всю рутиную работу переложить на библиотеки, с… twitter.com/i/web/status/1…
Добросовестные студенты нередко спрашивают, что почитать по Android. Обычно я рекомендую Effective Java (… twitter.com/i/web/status/1…
Именно по Андроид отсылаю на официальный сайт developer.android.com. Я в основном черпаю информацию из блогов на… twitter.com/i/web/status/1…
Если говорить про Medium, то это:
В чем я в итоге вижу проблему современных студентов и как следствие проблему кандидатов, приходящий на собеседовани… twitter.com/i/web/status/1…
Как следствие они не очень то умеют писать оптимальный код (по памяти, по производительности, про трафику). Они мог… twitter.com/i/web/status/1…
Может быть это и не плохо в прикладном программировании, но лично мне всегда было интересно как внутри устроен fram… twitter.com/i/web/status/1…
Почувствовал себя немного старпёром, который недоволен молодым поколением :)
Кстати, про понимание внутренностей. Пытался объяснить студентам, почему анонимные или нестатические вложенные клас… twitter.com/i/web/status/1…
@mobileunderhood eng.uber.com и другие блоги больших компаний тоже полезны
Да, у Uber просто эталонный технический блог. Читаю их в Твиттере - @UberEng. Также подписан на @SpotifyEng,… twitter.com/i/web/status/1…
Что-то последнее время @mobileunderhood сильно интереснее читать, чем @backendsecret. И это при том, что к мобилкам… twitter.com/i/web/status/1…
У меня в универе был препод по электродинамике, который сказал одну вещь, которая запала мне в душу: "Если вы не мо… twitter.com/i/web/status/1…
Именно это толкнуло меня пойти преподавать, так как захотелось систематизировать и углубить свои знания. Я преподав… twitter.com/i/web/status/1…
А также помогло прокачать навыки публичных выступлений. Так что если хотите навести порядок в своих знаниях и перес… twitter.com/i/web/status/1…
Еще о книгах. Попалась мне как-то книга "Joel on Software" (amazon.com/Joel-Software-…). Прочитал ее как художественну… twitter.com/i/web/status/1…
@mobileunderhood Я его блог читал ещё в начале 2000ых. Отличный кладезь информации про управление проектами и за жизнь )
Джоэл актуален во все времена twitter.com/yurabereza/sta…
@mobileunderhood Я в самом начале преподавания замыкания объяснял как "как функция захватывающая контекст и которую… twitter.com/i/web/status/1…
Сегодня было несколько вопросов, про то, как перейти в мобилки из других областей (я подразумеваю, что другие облас… twitter.com/i/web/status/1…
Уверенное владение языком и хорошее понимание того, как вообще работают компьютеры и операционные системы, помогли… twitter.com/i/web/status/1…
Я сам пришел в мобильную разработку из десктопной. Писал кроссплатформенные приложения на C# (Windows, Linux). Пото… twitter.com/i/web/status/1…
Мне повезло найти команду, в которой писали под мобилки, но на C#. Таким образом, я смог применить свой опыт, приче… twitter.com/i/web/status/1…
Итого рецепт вижу таким:
Кстати, а какое первое приложение вы делали, когда пришли в мобилки (коммерческое или pet project)?
Я делал черный… twitter.com/i/web/status/1…
@mobileunderhood <К.О.>Другие инженеры не всегда правы; решения, попавшые в продакшен, не всегда удачны.</К.О.>
Хороший афоризм на все случаи жизни :) twitter.com/miha_x64/statu…
Хочу подвести итог сегодняшнего дня и поиграть в предсказателя. Я вижу большой дефицит кадров на рынке труда. Круты… twitter.com/i/web/status/1…
При этом свежие кадры, которые поступают в индустрию, порой не выглядят перспективно. Многие идут в мобилки, узнав… twitter.com/i/web/status/1…
С учетом сказанного мне видится, что зарплаты хороших инженеров будут только расти, но при этом возрастет и количес… twitter.com/i/web/status/1…
Зато, если устроиться работать в хорошую компанию (пускай даже джуниором или стажером), то есть все возможности рас… twitter.com/i/web/status/1…
День 2. Кроссплатформа.
Тема достаточно спорная (особенно в мобилках). Много человеколет потрачено на обсуждения и… twitter.com/i/web/status/1…
@tapoton @AndreyMishanin @mobileunderhood На этом этапе нет. Всему свое время. Для начала пусть научаться писать ко… twitter.com/i/web/status/1…
Тут я полностью согласен, но к сожалению у меня курс по Android всего 14 лекций, в которые с трудом влезают самые о… twitter.com/i/web/status/1…
В коммерческую разработку мобильных приложений я пришел из мира десктопа и .NET. У меня уже были какие-то представл… twitter.com/i/web/status/1…
В том 2011 году идея кроссплатформенных приложений мне казалась свежей, актуально и гениальной - зачем писать под к… twitter.com/i/web/status/1…
На волне этой идеи меня затянуло в стартап, который делал мобильное приложение на Xamarin (MonoTouch для iOS и Mono… twitter.com/i/web/status/1…
Но суровая реальность все расставила по своим местам. Как-то не получилось писать одни раз код и везде запускать. В… twitter.com/i/web/status/1…
Оказалось, что UIButton и Button, UIImage и ImageView сильно разные. Как минимум по программному интерфейсу. Сейчас… twitter.com/i/web/status/1…
По факту оказалось, что кода у нас примерно 50/50. Бизнес логика, клиент-серверное взаимодействие (Apache Thrift) и… twitter.com/i/web/status/1…
@AndreyMishanin @tapoton @mobileunderhood Я хочу что бы люди не просто делали "потому что мне так сказали", а понял… twitter.com/i/web/status/1…
Понимание приходит с опытом. Нужно сначала сделать неправильно или плохо, осознать почему это плохо, выяснить почем… twitter.com/i/web/status/1…
С какими проблемами столкнулись:
3. С iOS-ным ARC тоже были конфликты. Особенно, в какой-то момент вышел новый generational GC, с которым наше iOS п… twitter.com/i/web/status/1…
Потом в какой-то момент Xamarin задрал цены. Если я правильно помню, то было 400$ per developer, а стало 1000$ per… twitter.com/i/web/status/1…
github.com/xamarin/xamari…
github.com/xamarin/xamari…
Да и сам Mono давно открыт
github.com/mono/mono
В дополнении к тому, что runtime отбирал на себя часть ресурсов системы, так еще и сами сборки (apk и ipa) были бол… twitter.com/i/web/status/1…
Есть мнение, что кроссплатформенная разработка дешевле, мол не надо нанимать две команды. Однако оказывается, что н… twitter.com/i/web/status/1…
Отсюда я сделал для себя вывод, что Xamarin и подобные фреймворки хорошо подходят для создания MVP и proof of conce… twitter.com/i/web/status/1…
Далее судьба меня кинула в игровую студию, писать мобильные игры. Жизнь столкнула меня с C++ и Lua. Вероятно, игры… twitter.com/i/web/status/1…
Знаю, что некоторые приложения пилят версию для iOS и Android на Qt. Решение рабочее, но дизайн Qt-компонентов не с… twitter.com/i/web/status/1…
@mobileunderhood Теперь для QtQuick вышел набор разных тем, в том числе и материальный дизайн
@mobileunderhood Да, есть такое. Очень много плюсов и минусов. Но с каждым годом найти мобильщика с С++ бэкграундом… twitter.com/i/web/status/1…
Многие интересуются насчет React Native. Пару лет назад я всерьез испугался за свою карьеру, потому что он был везд… twitter.com/i/web/status/1…
Тут ведь и Facebook, и Airbnb и другие IT гиганты.
Но в прошлом году Airbnb (между прочим один из главных контрибью… twitter.com/i/web/status/1…
Для меня это стало серьезным знаком, после которого я перестал опасаться за свою карьеру и стал скептически относит… twitter.com/i/web/status/1…
Теперь про Flutter. Я пока присматриваюсь к нему. На каждой конференции есть минимум один доклад про Flutter. Но я… twitter.com/i/web/status/1…
Я наблюдал уже за Xamarin, PhoneGap (Apache Cordova), ReactNative и вот сейчас Flutter. Время покажет :)
Немного поделюсь своим опытом работы с Lua/C++. Одну из игр мы сделали на C++ движке, но саму логику написали на Lu… twitter.com/i/web/status/1…
Я с большой любовью вспоминаю биндинги, которые я писал для Andoird. Lua <-> C++ <-> Java. А на стороне Java все ещ… twitter.com/i/web/status/1…
Если с частью Lua <-> C++ особых проблем не было (Lua заточен под это, так как позиционирует себя как встраиваемый… twitter.com/i/web/status/1…
Например, если Java-код кинет исключение, которое не будет корректно обработано в C++, то программа продолжит работ… twitter.com/i/web/status/1…
А какое удовольствие наблюдать как Java GC любезно управляет Java-объектами, созданными из C++. Все хорошо, кроме т… twitter.com/i/web/status/1…
@mobileunderhood Я немного о другом. На нем а разы (именно в разы) быстрее верстать UI благодаря jsx. Из этой верст… twitter.com/i/web/status/1…
@vvsevolodovich @mobileunderhood Понимаю, конечно, что это опечатка, но сорта RN — это хорошее начало 2к19
А потом я перешел в "нормальную" Android разработку и думал, что уж тут то не придется писать на C++. Но и тут меня… twitter.com/i/web/status/1…
Благо не пришлось погружаться в JNI-ад. Мы запускаем ffmpeg в отдельном процессе (грубо говоря so-шку в командной с… twitter.com/i/web/status/1…
@mobileunderhood @vvsevolodovich Когда я работал в EPAM, у нас всех мобильщиков в нашем офисе RN научили.. Я тоже с… twitter.com/i/web/status/1…
@mobileunderhood @gavrix По опыту могу сказать, что не стоит использовать малопулярные фреймворки (медленней развит… twitter.com/i/web/status/1…
@vvsevolodovich @starkyru @mobileunderhood Ну, AirBnB созрели только к 18-ой 😀 Кто-то любит своими граблями набиват… twitter.com/i/web/status/1…
Вспомнились еще подводные камни с нативным C++ кодом. По-хорошему в APK надо еще помимо arm сборок класть сборки дл… twitter.com/i/web/status/1…
Под вечер развернулось классное обсуждение вокруг RN. Пускай оно продолжается и дальше, а я пока подведу итоги сего… twitter.com/i/web/status/1…
Подводя итог, хочу сказать, что любой фреймворк, кроссплатформенный или нет - всего лишь инструмент в решении бизне… twitter.com/i/web/status/1…
День 3: Как заставить приложение работать в фоне
Сегодня поговорим о фоновой работе Android приложений и как Google… twitter.com/i/web/status/1…
С учетом моего небольшого опыта в iOS субъективно кажется, что на этой платформе дела обстоят несколько лучше, чем… twitter.com/i/web/status/1…
Большинству приложений хватает и тех инструментов, что идут из коробки, а каким-то работа в фоне вообще не актуальн… twitter.com/i/web/status/1…
Моя команда занимается разработкой мессенджеров. Кажется, что пользователи хотят получать сообщения мгновенно (не п… twitter.com/i/web/status/1…
Есть еще ряд категорий приложений, для которых важна оперативная доставка событий до клиента. Например:
Прежде чем погружаться в варианты реализации, стоит вообще рассмотреть, как ведет себя Android, когда приложение ух… twitter.com/i/web/status/1…
Если вспомнить Android времен 4.x и раньше, то интернет был полон шуток про батарею и постоянную необходимость заря… twitter.com/i/web/status/1…
В Android 6.0 (Marshmallow) Google начала закручивать гайки. Появились режимы экономии энергии: Doze Mode и App Sta… twitter.com/i/web/status/1…
В Android 8.0 (Oreo) Google пошла еще дальше и подрезала работу сервисов, по сути обязав их быть foreground сервиса… twitter.com/i/web/status/1…
Далее Google 1-го июля 2018 года запретил публиковать новые приложения без поддержки Android 8, а с 1-го ноября зап… twitter.com/i/web/status/1…
Давайте представим, что мы пишем мессенджер. Нужно показывать уведомление пользователю при получении сообщения. Пер… twitter.com/i/web/status/1…
Но FCM работает только на тех устройствах, где есть Google Play Store (по факту Google Play Services) -… twitter.com/i/web/status/1…
Вторая проблема с FCM в том, что нельзя посмотреть официальную статистику доставляемости пушей. Мы сейчас занимаемс… twitter.com/i/web/status/1…
@mobileunderhood И в январе 2019 уже можно говорить, что эта битва была проиграна дизайн тимой. Несмотря на наличие… twitter.com/i/web/status/1…
Особенно удручает поведение MIUI, которое не соответствует документации. Например, сервис запущенный с флагом START… twitter.com/i/web/status/1…
Как мы делали до 1-го ноября 2018 года. У нас в отдельном процессе был запущен Service, который держал long polling… twitter.com/i/web/status/1…
Кстати, запуск сервиса в отдельном процессе был одним из хаков обхода MIUI, так как смахивание приложения из рисент… twitter.com/i/web/status/1…
То есть по сути мы делали сами тоже самое, что делает FCM под капотом. Идея централизованного механизма для пушей е… twitter.com/i/web/status/1…
Однако ненадежность FCM все равно вынуждает разработчиков придумывать свои решения, дублирующие официальную функциональность.
@mobileunderhood Вот тут народ подсуетился и начал собирать инфу о производителях, их грехах и потенциальных страте… twitter.com/i/web/status/1…
1-го ноября Google вынудил нас поднять target api. Пришлось переделывать механизм long polling'а и выносить его из… twitter.com/i/web/status/1…
# FirebaseJobDispatcher
Все хорошо. Кроме того, что требует наличия Google Play Services на устройстве, а значит пр… twitter.com/i/web/status/1…
# JobScheduler
В отличие от FirebaseJobDispatcher не требует Google Play Services, но доступен с 21-й версии API, т… twitter.com/i/web/status/1…
# SyncAdapter
Жутко неудобный механизм, который, несмотря на название, редко кто использует по прямому назначению.… twitter.com/i/web/status/1…
# WorkManager
Лучше из перечисленных решений. Работает на Android 4.4, не требует наличия Google Play Services. Каз… twitter.com/i/web/status/1…
Хорошая сводная табличка есть тут - github.com/firebase/fireb…
Там перечислены указанные выше решения, их min api и за… twitter.com/i/web/status/1…
Таким образом, Google скрутил разработчикам руки еще 1-го ноября прошлого года, а достойного, удобного и надежного… twitter.com/i/web/status/1…
Более того все описанные выше решения (в том числе и WorkManager) имеют минимальный интервал, чаще которого не полу… twitter.com/i/web/status/1…
Итого мы остановились на WorkManager (на свой страх и риск, так как он в бете) с небольшим костылем, который пока б… twitter.com/i/web/status/1…
Далее мы запускаем работу, состоящую из FetchWorker'а и RestartWorker'а. Первый делает long-polling запрос на серве… twitter.com/i/web/status/1…
WatchDogWorker, как это следует из названия, просто раз в 15 минут проверяет, что это зацикленная цепочка, состояща… twitter.com/i/web/status/1…
@mobileunderhood В iOS свои сложности. Да, нет описанных проблем c зоопарком устройств/операционок. Но руки скручен… twitter.com/i/web/status/1…
@mobileunderhood Но описанная в треде история — это конечно жестко. У нас все закрывает APNS со своей непредсказуем… twitter.com/i/web/status/1…
@mobileunderhood Возможно кому-то пригодится. В iOS есть VoIP пуши которые умеют запускают приложение из убитого (N… twitter.com/i/web/status/1…
@jack_martynov Я недавно заглянул в статистику в консоли Google Play и ужаснулся, что на неподдерживаемых нами верс… twitter.com/i/web/status/1…
Коротко о фрагментации устройств под управлением Android twitter.com/mobileunderhoo…
Я тут решил освежить в памяти доку по doze mode - developer.android.com/training/monit…
И вспомнил, что SyncAdapter не работает в… twitter.com/i/web/status/1…
Хахаха. Из той же доки: The system does not allow JobScheduler to run.
На этом на сегодня всё. Спасибо тем, кто что-то добавил про iOS. Мне пора бы уже расширить свои компетенции на ябло… twitter.com/i/web/status/1…
P.S.: как бы мы не ругали Google и их политику насчёт батареи, но шуток про зарядку стало заметно меньше. Я букваль… twitter.com/i/web/status/1…
@mobileunderhood В Doze можно мутить "тяжелую" работу по синку либо во время окна (по дефолту), либо используя Igno… twitter.com/i/web/status/1…
@p01y4k0v @mobileunderhood Ну и продолжая, WorkManager - по большому счету это compat scheme для JobScheduler со вс… twitter.com/i/web/status/1…
От FCM мы не отказались. У нас и SyncAdapter даже есть. Главное - любым доступным способом поднять процесс, а дальш… twitter.com/i/web/status/1…
День 4: Кодогенерация
Разработчики ленивы по своей сути и хотят, чтобы код писал сам себя самостоятельно. Если прих… twitter.com/i/web/status/1…
Первое, что приходит в голову, когда слышу "кодогенерация" это APT - Annotation Processing Tool. Инструмент досталс… twitter.com/i/web/status/1…
Стоит отметить, что APT не связан напрямую с генерацией кода. Можно генерировать ресурсы, да и вообще файлы в любом… twitter.com/i/web/status/1…
Например, можно сделать аннотацию @HasDefaultConstrucor и annotation proccesor проверит, что у класса есть публичны… twitter.com/i/web/status/1…
Но чаще встречаются библиотеки, которые все же генерируют код при помощи APT. Навскидку вспоминается:
В общем большой плюс APT в том, что всё происходит в compile-time. Да, время сборки заметно увеличивается, но, напр… twitter.com/i/web/status/1…
На Medium есть статья с примерами кода (medium.com/@iammert/annot…), где можно подробней почитать про APT. Ну и всегда… twitter.com/i/web/status/1…
Если при обработке какой-то аннотации произошла какая-то ошибка, то APT позволяет не только отписать ее в build log… twitter.com/i/web/status/1…
Например, у аннотации стоит @Target(ElementType.TYPE). Это значит, что ее можно повесить или на класс, или на интер… twitter.com/i/web/status/1…
Тут правильно подсказывают, что генерация кода (в частности через APT) хорошо решает проблему большого количества b… twitter.com/i/web/status/1…
При написании своих процессоров аннотаций рано или поздно возникает вопрос - как тестировать этот процессор и как п… twitter.com/i/web/status/1…
Коротко о принципах ее работы:
Например: pic.twitter.com/OQU8BH08PD
Таким образом можно покрыть тестами код самого процессора, но проверить сгенерированный код можно по факту только п… twitter.com/i/web/status/1…
Более того даже при совпадении actual и expected кода нет никакой гарантии, что expected код в принципе корректный.… twitter.com/i/web/status/1…
Поэтому вдохновившись идеей compile-testing я сделал свою библиотеку, которая позволяет не просто проверить сгенери… twitter.com/i/web/status/1…
С compile-time кодогенерации переключимся на генерацию в runtime. Поговорим о dynamic proxy в Java. Оказалось, что… twitter.com/i/web/status/1…
На официальном сайте Oracle есть статья от том, что такое dynamic proxy и с чем его едят - docs.oracle.com/javase/8/docs/…… twitter.com/i/web/status/1…
Допустим у нас есть интерфейс Foo с методом bar. Мы можем в runtime создать объект, который имплементирует этот инт… twitter.com/i/web/status/1…
Наверное, самый известный в Android мире пример использования dynamic proxy - библиотека Retrofit (square.github.io/retrofit/).
В нашем проекте мы используем dynamic proxy для работы со статистикой. У нас есть интерфейс Stat, который описывает… twitter.com/i/web/status/1…
Аннотация Key нужна для получения имени параметра, так как в runtime через рефлексию нельзя получить имена аргумент… twitter.com/i/web/status/1…
@mobileunderhood Performance характеристики у этого метода те же, что и использования reflection? Что следует учиты… twitter.com/i/web/status/1…
Да, performance не блещет. Злоупотреблять прокси-вызовами не стоит. Время вызова примерно в 80 раз больше, чем у пр… twitter.com/i/web/status/1…
Иногда удобно использовать dynamic proxy для прокидывания callback'ов о listener'ов в сторонние библиотеки, когда т… twitter.com/i/web/status/1…
Что-то в таком духе pic.twitter.com/Abx0bzKyVH
Когда в Java коде имеется nullable callback или listener, а в каждом месте перед вызовом метода лениво проверять ег… twitter.com/i/web/status/1…
К сожалению java.lang.reflect.Proxy работает только с интерфейсами. Сгенерировать прокси объект для абстрактного кл… twitter.com/i/web/status/1…
Забыл, собственно, про кодогенерацию. Ведь APT это просто инструмент для обхода элементов кода, помеченных указанно… twitter.com/i/web/status/1…
На правах рекламы еще расскажу про свою библиотеку autoprefs (github.com/int02h/autopre…), которая при помощи APT и Ja… twitter.com/i/web/status/1…
На этом на сегодня всё. Коротко резюмирую сегодняшний день:
@mobileunderhood Во! Вот это уже интересно!
День 5: Темизация приложения
Из обсуждения кода и его генерации плавно перейдем к визуальной составляющей наших при… twitter.com/i/web/status/1…
Исторически у нас в приложении была одна зеленая тема. Соответственно, у нас был один файл colors.xml с палитрой, н… twitter.com/i/web/status/1…
В какой-то момент пользователи начали активно просить сделать темную тему. Мы выделили какие-то общие части в базов… twitter.com/i/web/status/1…
То есть, например, при тинтовании drawable-ресурсов мы уже не могли напрямую ссылаться на цвет, типа "@color/primar… twitter.com/i/web/status/1…
То же самое и ColorStateList. Только в нем атрибуты темы можно использовать вообще начиная с API Level 23 (Android 6.0).
Из-за этого пришлось либо делать какие-то вещи программно (например, тинтовать drawable), либо делать 2 похожих рес… twitter.com/i/web/status/1…
Теперь уже разработчик не мог держать в голове всю темизацию. Если нужно было править Drawable или ColorStateList,… twitter.com/i/web/status/1…
@mobileunderhood Темы в андроиде это вообще боль хотя если очень сильно постараться, то можно накатать немного бинд… twitter.com/i/web/status/1…
Дальше у нас назрела синяя тема. Дизайнеры уверяли, что от зеленой будет отличаться только акцентным цветом. Поэтом… twitter.com/i/web/status/1…
По факту мы сделали две ошибки:
В итоге мы пришли к ситуации, когда разработчик абсолютно не понимал где нужно менять цвет, если он хочет поправить… twitter.com/i/web/status/1…
@SerhiiChaban @mobileunderhood Темы в iOS — это вообще выдумка :(
Стало очевидным, что наследование тем - плохое решение, которое тяжело поддерживать. Мы решили избавиться от него,… twitter.com/i/web/status/1…
Мы начали с цветов. Дизайнеры составили палитру. Нам они передали .sketch файл, который мы распарсили и на выходе п… twitter.com/i/web/status/1…
То есть вместе с тремя файлами цветов генерировались три файла тем, пока только с атрибутами цветов из палитры. Ста… twitter.com/i/web/status/1…
Затем мы избавились от копипастных drawable-ресурсов, так как для одного ресурса было уже 3 файла с практически оди… twitter.com/i/web/status/1…
По аналогии сделали шаблоны для ColorStateList.
Такое шаблонизирование решило проблему правок одного ресурса в разн… twitter.com/i/web/status/1…
Также генератор, который превращает шаблоны в результирующие xml-файлы, создает в файлах тем атрибуты для Drawable… twitter.com/i/web/status/1…
Для нашего генератора мы сделали инкрементальную таску в Gradle скрипте, которая срабатывает только при изменении п… twitter.com/i/web/status/1…
Также мы убрали почти все ресурсы из под git'а и оставили под контролем версий только палитру и шаблоны.
Итого, что делает генератор:
Наследование тем осталось, но теперь выглядит по другому: ApiDependentTheme <- AbstractTheme <- GeneratedTheme
В са… twitter.com/i/web/status/1…
Общая абстрактная тема в основном содержит настройку системных атрибутов типа "?android:attr/*"
Автоматизация темизирования позволила разработчику выкинуть из головы нюансы темизации и просто использовать атрибу… twitter.com/i/web/status/1…
За консистентность приложения с точки зрения темизации теперь отвечают дизайнеры, так как они поставляют нам палитр… twitter.com/i/web/status/1…
За подробностями насчет автоматизации темизации Android-приложения можно обратиться к моему докладу на Android Devs… twitter.com/i/web/status/1…
Меня одолело любопытство и под вечер я решил провести небольшой опрос.
Сколько различных цветовых тем в вашем мобильном приложении?
Такое автоматизированное решение позволяет безболезненно добавлять любое количество новых тем в приложение и с легк… twitter.com/i/web/status/1…
День 6: Логирование и сбор ошибок
Сегодня поговорим о том, как понять, что в приложении что-то пошло не так. А глав… twitter.com/i/web/status/1…
Начнем разговор со сборка крэшей. Ни для кого не секрет, что окошко "приложение завершило работу" не радует ни поль… twitter.com/i/web/status/1…
Я работал в разные периоды времени с HockeyApp, Crashlytics (он сейчас в составе Firebase), Firebase Crash Reportin… twitter.com/i/web/status/1…
В последнее время в проекте мы использовали HockeyApp и Crashlytics. Каждая из них имеет свои преимущества и недост… twitter.com/i/web/status/1…
Так сложилось, что для HockeyApp мы практически не используем их Android SDK, а шлём креши сами. У нас есть единый… twitter.com/i/web/status/1…
Именно так наша нативная команда формирует свои нативные креши, чтобы потом можно было их удобно просматривать и де… twitter.com/i/web/status/1…
Поскольку крэши пишем мы сами, а не средствами HockeyApp SDK, то и всю дополнительную информацию помимо stack trace… twitter.com/i/web/status/1…
Мы прикрепляем к каждому крэшу следующую информацию:
Поскольку крэши мы формируем сами (по сути просто записывая специальный файл), то мы можем отписывать ошибки, котор… twitter.com/i/web/status/1…
В принципе в Crashlytics также есть разделение на fatal и non-fatal ошибки. Если приложение ведет себя неправильно,… twitter.com/i/web/status/1…
Мотивация к появлению silent крэшей была примерно следующей: Java обязывает программиста обработать исключение, есл… twitter.com/i/web/status/1…
Поэтому если какой-то код попадёт в исключительную ситуацию, то мы об этом обязательно узнаем. Наверное, самый част… twitter.com/i/web/status/1…
Что касается IOException при работе с сетью, то мы выделили отдельный проект в HockeyApp, куда отписываем ошибки пр… twitter.com/i/web/status/1…
Конечно, тема с серверными ошибками спорная, типа сервер должен сам следить за своей работой.
Но пользователь жалуе… twitter.com/i/web/status/1…
Итого у нас в HockeyApp заведено аж 5 проектов:
Для релиза мы собираем 6 APK: сплит для пяти различных dpi и одну универсальную сборку. Чтобы все ошибки с версии б… twitter.com/i/web/status/1…
Спрашивают, как я делаю картинки с кодом для постов. Я использую сервис carbon.now.sh
При отправке крэша на старте приложения мы попутно отправляем в систему статистики событие об отправке. Это помогае… twitter.com/i/web/status/1…
Думаю, на сегодня хватит. Не буду грузить вас в выходные. Если остались вопросы - с удовольствием отвечу. Хорошего вечера!
День 7: День релакса, общения и набросов.
Сегодня темы конкретной нет. Предлагаю пообщаться на разные темы около мо… twitter.com/i/web/status/1…
Про архитектуру уже много было споров, но вот вам ещё маленький вброс. Если смотреть на Clean Architecture, то сущн… twitter.com/i/web/status/1…
Постоянное создание мелких объектов (особенно если это массивы объектов) и копирование данных между ними отнимает р… twitter.com/i/web/status/1…
@mobileunderhood Иногда не нужно слепо следовать гайдлайнам архитектуры просто потому что так дядя Мартин написал.… twitter.com/i/web/status/1…
Подпишусь под каждым словом twitter.com/p01y4k0v/statu…
@mobileunderhood Как там говорится: «Преждевременная оптимизация - корень всех зол» кмк гибкость кода на первых пор… twitter.com/i/web/status/1…
@mobileunderhood Правильная архитектура всегда будет не самым эффективным решением с точки зрения перфы, но в абсол… twitter.com/i/web/status/1…
@mobileunderhood Мне кажется, что Clean Architecture в целом не очень применима к Андроиду (не знаю как там с iOS).… twitter.com/i/web/status/1…
@mobileunderhood Плюс порой есть возможность считерить, например, в kotlin использовать "typealias Layer2Model=Laye… twitter.com/i/web/status/1…
Кого еще вы хотели бы видеть ведущим @mobileunderhood? Фопмирую расписание на март-апрель, так что накидывайте!
@AndreyMishanin @mobileunderhood Почему у нас в Swift обращение к несуществующему ключу словаря даёт nil, а к несущ… twitter.com/i/web/status/1…
Чтобы было, что спрашивать на собеседованиях twitter.com/tygeddar/statu…
Да, вброс "архитектура vs performance" вызвал бурное общение и это очень круто. В споре рождается истина. Если бы б… twitter.com/i/web/status/1…
Вношу вторую тему на обсуждение. Стоит ли тащить в проект все необходимые сторонние библиотеки или же иногда стоит… twitter.com/i/web/status/1…
Буквально 1.5 года назад мы знатно упарывались, чтобы оставаться в пределах 65k методов. Это накладывало определенн… twitter.com/i/web/status/1…
Более того у нас есть негласное правило, что в проект мы тащим только те либы, чьи исходники мы изучали и примерно… twitter.com/i/web/status/1…
@mobileunderhood +, js’никам бы это все прочитать, leftpad, код который шлёт ключи налево...
Про leftpad мой любимый аргумент в спорах про сторонние библиотеки :) twitter.com/medvezhopok/st…
@mobileunderhood большое спасибо Даниилу Попову за эту неделю, было очень познавательно и по делу. Эта первая недел… twitter.com/i/web/status/1…
@mobileunderhood На моем опыте, после изучения исходников часто становится понятно что половина этой библиотеки не… twitter.com/i/web/status/1…
Раз уж у нас сегодня день общения и вбросов, то мне жутко интересно узнать мнение сообщества по следующему вопросу:… twitter.com/i/web/status/1…
@mobileunderhood На одном проекте у нас была политика, что если 1) писать самим меньше пары дней или 2) это «центра… twitter.com/i/web/status/1…
На этой неделе я всё. Я считаю, что мы круто пообщались. Мне очень понравилось! Постараюсь поднять из руин свой бло… twitter.com/i/web/status/1…
Кстати, если вам интересно то, о чем я говорил на этой неделе, то приходите к нам работать. Все темы этой недели по… twitter.com/i/web/status/1…
Пользуясь переходным периодом между двумя авторами, задам важный вопрос. Стоит приглошать англоязычных ведущих?
- https://github.com/xamarin/xamarin-macios
- https://github.com/xamarin/xamarin-android
- https://github.com/mono/mono
- https://github.com/firebase/firebase-jobdispatcher-android#comparison-to-other-libraries
- https://github.com/int02h/autoprefs
- http://mail.ru/
- http://developer.android.com/
- https://developer.android.com/reference/android/app/AlarmManager.html#setAlarmClock(android.app.AlarmManager.AlarmClockInfo,%20android.app.PendingIntent)
- https://developer.android.com/training/monitoring-device-state/doze-standby#restrictions
- https://proandroiddev.com/
- https://android.jlelse.eu/
- https://medium.com/mindorks
- https://medium.com/@iammert/annotation-processing-dont-repeat-yourself-generate-your-code-8425e60c6657
- http://otus.ru/
- https://www.amazon.com/Joel-Software-Occasionally-Developers-Designers/dp/1590593898
- https://www.androidpolice.com/2019/01/13/dontkillmyapp-com-shames-oems-that-needlessly-kill-useful-background-processes-to-save-battery-life/
- https://docs.oracle.com/javase/8/docs/technotes/guides/reflection/proxy.html
- https://square.github.io/retrofit/
- https://carbon.now.sh/
- http://carbon.now.sh/