Блог Android-разработчицы
849 subscribers
13 photos
179 links
ex-VK, ex-MTS, 6+ лет опыта. Team Lead

Заметки, интересные задачи с работы (в рамках NDA) и просто мои мысли.

Блог: https://dzen.ru/android_junior

Личный канал: https://t.me/android_junior_notes

Мой аккаунт: https://t.me/bagena
Download Telegram
Вчера был доклад на вечную тему «Как сделать, чтобы проект собирался быстрее», но с интересным посылом «Как (не) ускорить сборку Android-проекта». Видео по ссылке: https://youtu.be/9YGScnDosN8?t=7063. Не сказать, чтобы я узнала что-то новое, но в целом докладчик хорошо рассказывает. А ещё он против модуля buildSrc, который я очень люблю. И он не упомянул, что в 7 gradle были большие доработки, так что с buildSrc не всё так плохо.

Кстати, я удивилась, когда докладчик сказал, что nonTransitiveRClass особо не ускоряет. Я читала, что он увеличивает скорость чуть ли не на 20%. Это было прям открытие для меня. Интересно всё-таки будет проверить на большом проекте, но для этого нужно, чтобы на этом большом проекте был седьмой gradle.

P.S. само видео почти на 2,5 часа, но имеет смысл смотреть только последний доклад. Остальное было про iOS.
А точно каждый компонент должен быть зарегистрирован в манифесте?

Нет, не точно. Broadcast Receiver можно зарегистрировать двумя способами: статически в манифесте или динамически в коде.

Стоит заметить, что начиная с Android 8 большинство неявных бродкастов нельзя регистрировать в манифесте. Неявный бродкаст, это когда сообщение отправляется вообще всем приложениям, которые подходят, а не только нашему. Почему нельзя? В Android 8 были большие доработки по оптимизации. Представьте, что куча приложений подписаны на какое-то системное событие. Каждый бродкаст в этом случае потребляет ресурсы каждый раз при получении сообщения. В следствии этого активно тратится батарея, пользователь грустит и удаляет приложение.

Но все еще можем регистрировать в коде.

Список всех интентов, для которых неявный бродкаст можно в манифесте регистрировать — https://developer.android.com/guide/components/broadc...

Из тех, которые я помню:

ACTION_BOOT_COMPLETED — отправляется один раз при загрузке. Необходим для многих приложений, чтобы они все проинициализировались, запланировали что им надо и прочее.

ACTION_TIMEZONE_CHANGED и похожие — чтобы приложении могли свои настройки поправить (например, будильники).

ACTION_CONNECTION_STATE_CHANGED — чтобы приложения знали про соединение.

Еще есть всякие флаги, связанные со звонками, сообщениями, сетью и сменой/удаления пользователя.

Google рекомендует использовать JobSheduler вместо неявных бродкастов.

Какие вопросы можно задать из этого ответа?

— А какие еще ограничения есть?

— Что за JobSheduler и почему его?
👍1
Почему setContentView() надо обязательно указывать в onCreate() в активити? Почему не в onResume или в onViewCreated?

Тут надо вспомнить жизненный цикл активити. Ответ кроется в том, что onCreate у активити вызывается только один раз. Именно в этом методе мы делаем большинство инициализаций.

setContentView() — метод, который позволяет разместить пользовательский интерфейс на экране. И это достаточно тяжелая операция, особенно учитывая, что может быть очень сложная иерархия. Её нужно делать один раз. Если делать каждый раз в onResume, то, например, просто посмотрев уведомление в шторке, операция будет выполняться снова, что ухудшает производительность, приложение может подвиснуть, пользователь расстроится и напишет гневный отзыв.

Вопросы, которые можно задать?

— Какие параметры можно передать в setContentView?
— Какой жизненный цикл у активити?
— А есть еще какие-то методы, которые вызываются только один раз?
— Как работает onCreate?
— Что будет, если мы вызовем finish() в одном из колбэков жизненного цикла, а чуть дальше напишем что-то еще?

Выполнится весь метод и только потом произойдет завершение. Почему так?

Все методы жизненного цикла всегда обрабатываются в главном потоке в порядке очереди. И вот если мы вызовем finish() в одном из методов жизненного цикла, то в эту очередь добавится сообщение, но оно не будет выполнено, пока не вернется выполняемый callback, т.е. пока главный поток не освободится от текущей задачи.

— Когда в activity вызывается finish(), какие методы жизненного цикла вызываются?

onPause — onStop — onDestroy. Тут важно, что метод onSaveInstanceState не вызывается, потому что активити полностью уничтожается.
Какая разница между val и var?

Такое точно не спросят, но просто повторим для общего образования.

var — изменяемое значение. Переменная может изменить свое значение с одного на другое. Это аналогично тому как мы в Java объявляем переменные.

val — переменная, которая разрешает чтение, но запрещает запись. Из этого следует, что val должна быть проинициализирована сразу, потому что она не может меняться после создания.
Разница между const и val

Оба слова используются для объявления неизменяемой переменной. Так в чем же разница?

const используется для объявления тех свойств, которые являются неизменяемыми по своей природе, т.е. они должны определяться во время компилирования. Во время выполнения константу нельзя объявить и проинициализировать.

Для констант есть несколько требований:

— Должна быть на уровне top-level или членом object или companion object

— Это должна быть строка или примитивный тип;

— Без кастомных геттеров.

Из этого следует, что мы не можем сделать константой какую-то функцию или класс, потому что они инициализируются в рантайме.

val мы можем инициализировать в рантайме. Например, можно в коде написать что-то в стиле valCatName = getCatName() и оно будет работать.

Зачем использовать const, если можно всегда использовать val? Когда мы используем константу, то она создается во время компиляции и не будет никаких дополнительных расходов во время выполнения.