А я сейчас читаю...
126 subscribers
5 photos
7 links
Канал посвящён конспектами, заметками, рецензиями известных книг по Java, Kotlin, Android, SQL и прочее.

Автор: @MrDragoRozum
Download Telegram
5.1. Не используйте несформированные типы

Ибо нет повода.

Несформированный тип выглядят следующим образом:

List list = new ArrayList();


В этом листинге не был указан (фактический параметр) типа (List<Object>...), посему был определен как несформированный (сырой) тип.

Поводы использовать такой тип в современном проекте нет от слова вообще, их нужно избегать. Причина: вы теряете все преимущества безопасности типов от обобщения, посему вы будете видеть не ошибки во время компиляции по поводу неверного типа для обобщения, а исключение ClassCastException в рантайме.
Они нужны для обратной совместимости и взаимодействия с кодом, написанным до появления средств обобщенного программирования.

Однако, есть исключения из правила «не использовать сырые типы»: либо нам нужно получить у обобщенного типа литерал класса (.class), либо в сочетании instanceof (в Kotlin — это is).

#Джошуа_Блох
#Эффективное_программирование_Java
#Заметки
#Глава_5
🔥5
5.2. Устраняйте предупреждения о непроверяемом коде

Подглава посвящена про предупреждения «Type safety: Unchecked cast».

Если ваш код выводит такое предупреждение, то нужно постараться от него избавиться, ибо это потенциальный источник ClassCastException. Если все попытки не удались, но при этом код безопасный и нет повода сгенерировать – то исключение, можно смело указать @SuppressWarnings("unchecked"). В противном случае можно потерять действительно критическое предупреждение среди тех многочисленных предупреждений.

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

Желательно также прокомментировать причину установки аннотации и почему код безопасный.

#Джошуа_Блох
#Эффективное_программирование_Java
#Заметки
#Глава_5
👍4
Какой результат выполнения этой программы?
Anonymous Quiz
30%
42
40%
Исключение ClassCastException
30%
Ошибка во время компиляции
5.3. Предпочитайте списки массивам

И да, тут не про то, что массив статический, а список динамический.

Если отбросить сравнение по структурам данным, то различие между ними такое:

1. Массивы ковариантные, в то же время списки инвариантные;
2. Массивы знают о своем типе в период выполнения и обеспечивают его, в то же время списки знают о своем типе в период компиляции.

Если смотреть по коду, то выглядит так:
Object[] objectArray = new Long[l];
objectArray [0] = "I don’t fit in"; // Исключение ArrayStoreException

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

List<Object> ol = new ArrayList<Long>(); // Несовместимые типы
ol.add("I don’t fit in");

Но благодаря инвариантности мы заметим проблему в период компиляции кода.

С первого пункта исходит и второй пункт, который также демонстрирует особенность между массивом и списком.

Я думаю, что мне не стоит расписывать, почему нужно использовать списки вместо массивов и тем более тогда, когда появляется потребность использовать обобщения.

#Джошуа_Блох
#Эффективное_программирование_Java
#Заметки
#Глава_5
❤5🔥2
5.5 Предпочитайте обобщенные методы

Очередной совет для тем, кто выступает против дженериков по каким-либо религиозным причинам.

Но меня больше привлек другое: автор вводит термин «рекурсивное ограничение типа» (recursive type bound). Как он выглядит? Предоставлю пример Collection.max():

public static <E extends Comparable<E>> E max(Collection<E> c) {
if (c.isEmpty()) {
throw new IllegalArgumentException("Пустая коллекция");
}

E result = null;
for (E e : c) {
if (result == null || e.compareTo(result) > 0) {
result = Objects.requireNonNull(e);
}
}

return result;
}

Цель такого подхода: ограничить тип и также получить доступ к методам родителя. В данном примере тип E должен расширяться от Comparable, который переопределяет методы, используя тип E. Можно читать как «Любой тип E, который можно сравнивать с самим собой».

Есть более наглядный пример объяснения.

#Джошуа_Блох
#Эффективное_программирование_Java
#Заметки
#Глава_5
❤4🔥1
Дочитал "Грокаем алгоритмы".

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

Есть, конечно, опечатки и некоторые иллюстрации, которые могут вводить даже в заблуждение и могут возникнуть некоторые сложности с самим языком Python (что будете тратить время ещё на его изучение).

Для кого это вообще книжка: для тех, кто вообще не понимает в структурах данных и алгоритмах (и не хочет в долгосрок). Даст достаточно приемлемое концептуальное понимание известных структур данных и ряд алгоритмов.

Однако реализации ряд структур данных особо не ждите (кроме графов и алгоритмов, их реализации предостаточно), ибо закладываются основные концепции и дополнительные детали могут лишь усложнить и так не простую тему; тем не менее сможете кое-что рассказать о них после прочтения и также послужит основой для других целей: для изучения более сложных материалов или как начальный старт к алгособесам.

#Бхаргава_Адитья
#Грокаем_алгоритмы
#Рецензия
👍7🔥1
🐗 2. What is the purpose of Pending Intent?

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

Где может быть использован PendingIntent:
1. Для запуска Activity;
2. Для запуска Service;
3. Для отправки broadcast.

Примеры использования:
1. Запуск Activity при клике на уведомление;
2. Для планирования через AlarmManager;
3. Делегирование задач ForegroundService для фоновых задач.

В своей очереди PendingIntent присутствуют ряд флагов для его функциях, например, FLAG_UPDATE_CURRENT, который обновляет существующей обертке новыми данными. Но есть флаг FLAG_IMMUTABLE, который обязательно нужно устанавливать всем оберткам для защиты от внешних изменений от вредоносных приложений; начиная с Android 12 для некоторых задач считается обязательным флагом.

#Manifest_Android_Interview
#Заметки
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥12
🐗 4. What is Context and what types of Context exist?

Тема достаточно обширная, посему пост получился большой.

Context предоставляет доступ к ресурсам и классам, необходимым для нашего приложения. Или, иными словами, он действует как "мост" между приложением и Android-системой, позволяя компонентам нашего приложения получить: доступ к ресурсам (assets например), базе данных (SQLite), системным сервисам (getSystemService) и другим.

Какие есть виды Context:
• Application Context — привязан к ЖЦ приложения. Выступает как долгоживущий контекст и используется, когда передаем тому, что живёт долго или читает ресурсы:
◦ SharedPreference или базы данных;
◦ Инициализация библиотек, например, Room.
• Activity Context — привязан к ЖЦ Activity. Используется в основном для UI операциях:
◦ Создание или модификация UI-компонентов;
◦ Запуск другой Activity;
◦ Доступ к ресурсам (res/).
• Service Context — привязан к ЖЦ Service. Используется преимущественно для фоновых задач и получения доступа к системным сервисам.
• Broadcast Context — предоставляется при вызове BroadcastReceiver и обычно используется для ответа на конкретные бродкасты, посему недолго живёт и из-за этого категорически не стоит использовать для долговременных задач.

Видим, что контексты различаются по времени жизни и допустимым задачам для них. Поэтому присутствуют распространенные ошибки, которых необходимо избегать:
• Преднамеренное задержание "мертвых" контекстов. Например, в классе-одиночке указали ссылку на ActivityContext, который со временем будет уничтожен: смена конфигурации. GC не может никак удалить этот контекст, поэтому получаем "утечку памяти";

• Неправильное использование контекстов. Например, воспользовались ApplicationContext для запуска диалога, хотя ожидается ActivityContext. У каждой реализации Context по-разному переопределены методы, посему мы можем получить неожиданные результаты;

• Использование контекста после уничтожения связанного компонента. Например, мы используем ActivityContext для View, когда его Activity уничтожили. В таком случае мы можем получить ошибки, так как ресурсы из Activity для Context будут тоже уничтожены;

• Использование контекста вне главного потока. Контекст предназначен для главного потока, особенно это выражается в доступе к ресурсам или во взаимодействии с UI. В противном случае мы можем получить проблемы, характерные для потоков, и сбои.

Существует также особый Context, который реализовывает паттерн «Декоратор» и даёт нам возможность добавлять новую функциональность нашим контекстам — ContextWrapper.

Но подробно о ContextWrapper не буду говорить, ибо его редко кто использует напрямую. Но он нужен для дальнейшего понимания. В Activity присутствует одна переменная — baseContext. Что это такое? Это ссылка на декорируемый объект (Context) в ContextWrapper, которому наделяют новую функциональность: возможность запускать активити, работать с UI-элементами и прочее. Благодаря этому «обычный» Context превращается в ActivityContext. Вам обычно не нужен baseContext, ибо в основном используется в реализации собственных контекстов.

#Manifest_Android_Interview
#Заметки
Please open Telegram to view this post
VIEW IN TELEGRAM
👍9🔥2
12. How to handle configuration changes?

Для чего обрабатывать изменения конфигурации (поворот экрана, переключение темным и светлым режимами и так далее) очевидно: пользователю не очень понравится потерять актуальное состояние экрана после очередного изменения конфигурации. Например, когда в TextField уже введено более 1000 символов и потом стал пустым из-за темного режима.

Тем не менее существуют наиболее распространённые способы решения подобной проблемы:

• onSaveInstanceState() и onRestoreInstanceState() — классический способ сохранения и восстановления UI-состояния;
• Jetpack ViewModel — позволяет данным пережить изменения конфигурации, поскольку живёт дольше Activity. Более предпочтительный способ, если это касается State всего экрана;
• rememberSaveable() — compose-способ сохранения состояния, основанный на механизме сохранения состояния Activity;
• onConfigurationChanged() — особый способ ручной обработки отдельных изменений конфигурации без пересоздания Activity. Используется редко и только в особых случаях. В неумелых руках можем получить очень кривой результат и это в лучшем случае.

#Manifest_Android_Interview
#Заметки
🔥4
Please open Telegram to view this post
VIEW IN TELEGRAM
14. What are the main causes of ANR errors, and how can you prevent them from occurring?

ANR (Application Not Responding) — это ошибка в Android, возникающая когда приложение слишком долго не отвечает на системные события или действия пользователя. Это ухудшает пользовательский опыт, а вы в своем очереди получаете шишки от QA-отдела и дополнительные задачи в джире поэтому поводу.

Факторы, которые могут привести к этой ошибке, — целый вагон и маленькая тележка:

- Сложные, долгие вычисления (например, обработка больших объёмов данных);
- Долгие IO операции: Network, database например;
- Банальный Thread.sleep в UI-потоке и подобному.

Как предотвратить ANRs
Всё, что может задержать выполнение главного потока, необходимо выносить в другие потоки. Основные практики по этому моменту:

- Перенести IO задачи за пределы главного потока. Выше про это упоминалось. Если у нас корутины, то очевидно нужно выносить в Dispatchers.IO;
- Для длительных фоновых операций можно использовать WorkManager или Foreground Service, чтобы не выполнять их в UI-потоке;
- Оптимизировать загрузку данных. Не загружать и не обрабатывать большие объёмы данных за один раз, для этого часто используют пагинацию.;
- Также касается длительных циклов, sleep и прочих, что ожидаемо может заблокировать главный поток;
- Не блокировать главный поток через Thread.sleep() для отложенного выполнения. В таком случае стоит использовать неблокирующие механизмы вроде delay() или Handler.postDelayed().

Однако, даже если основные или похожие практики соблюдены, но всё равно ANR ошибка возникает, то очевидно что уже пора смотреть проблему вглубь: использовать Android Studio Profiler для поиска узких мест, смотреть логи от Google Console и прочие инструменты для обнаружения и решения проблемы.

#Manifest_Android_Interview
#Заметки
❤3
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
Прочёл "Android Software Internals Quick Reference".

Зачем я взял эту книгу на прочтение? Цель была в получении сведения о Android Security, которая появилась после одного собеседования по поводу этого же раздела. Узнал об этой книжке и решил прочесть.

Страницы 170, справочная информация, каждая глава -- самодостаточна, то есть читать можно выборочно. Листинг кода без особого оформления, посему читать будет неприятно. Присутствуют графические изображения, но в малом количестве и достаточно информативные. Также есть главы с перечислением известных констант (ACTION, CATEGORY у Intent), что полезно однако. Размер страницы маленький, что можно прочесть за один день.

Удовлетворило мою цель? Скорее нет, чем да. Если выделить главы, которые полезны с точки зрения безопасности, то это частично "Storage", "Obfuscation and Encryption", и "Decompiling and Disassembling Android Applications".
Всё остальное либо и так знал, либо устаревшее (например, глава "Android Unique Identifiers" устаревшая и читать мало полезно, также касается и всех других глав, ибо есть устаревшие темы), либо сухо описано, что пришлось открывать даже "The Busy Coder's Guide to Advanced Android Development", чтобы получить больше сведение (хотя автор обмазывается сносками на документацию, но всё же ожидается, что было кратко и понятно, а не кратко и непонятно).

Стоит читать?

Если новичок, то только с чашечкой чая и без серьезного вчитывания, ибо ожидается, что вы проходите основной курс обучения, а это как дополнительное;
Если есть опыт разработки, то только выборочно и то, что интересно;
Если как руководство использовать, то может быть, но сейчас есть GPT и агенты, которые расскажут (очевидно не без факт-чекинга) лучше и сделают современным, актуальным образом."

Кстати, у этой книги прайс 47 евро... Лучше возьмите что-нибудь другое.

#Android_Software_Internals_Quick_Reference
#Рецензия
❤8🔥2👍1
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥7❤1👍1👎1