Невозможно отучить людей изучать самые ненужные предметы.
Введение в CSS
Преимущества стилей
Добавления стилей
Типы носителей
Базовый синтаксис
Значения стилевых свойств
Селекторы тегов
Классы
CSS3
Надо знать обо всем понемножку, но все о немногом.
Идентификаторы
Контекстные селекторы
Соседние селекторы
Дочерние селекторы
Селекторы атрибутов
Универсальный селектор
Псевдоклассы
Псевдоэлементы
Кто умеет, тот делает. Кто не умеет, тот учит. Кто не умеет учить - становится деканом. (Т. Мартин)
Группирование
Наследование
Каскадирование
Валидация
Идентификаторы и классы
Написание эффективного кода
Вёрстка
Изображения
Текст
Цвет
Линии и рамки
Углы
Списки
Ссылки
Дизайны сайтов
Формы
Таблицы
CSS3
HTML5
Блог для вебмастеров
Новости мира Интернет
Сайтостроение
Ремонт и советы
Все новости
Справочник от А до Я
HTML, CSS, JavaScript
Афоризмы о учёбе
Статьи об афоризмах
Все Афоризмы
Помогли мы вам |
Ограничения на показ оверлеев. С новой версии Android больше не предоставляет разрешение на показ оверлеев (окон поверх экрана) автоматически для предустановленных приложений. Исключение сделано только для системных приложений, располагающихся в каталоге /system. ОС также налагает ограничения на оверлеи. Теперь приложения не могут использовать непрозрачные оверлеи, которые пропускают через себя нажатия (раньше с их помощью пользователя вынуждали нажать определенные элементы интерфейса, перекрыв их безобидным окном). Кроме того, приложения теперь могут попросить систему не показывать оверлеи поверх своих окон с помощью разрешения HIDE_OVERLAY_WINDOWS
.
Возможность отключить 2G. Android 12 позволяет отключать поддержку сотовых сетей стандарта 2G в настройках смартфона, чтобы защититься от атак, использующих понижение до 2G.
Улучшения Wi-Fi. Android 12 поддерживает WPA3 Hash-to-Element (H2E), WPA2/WPA3-Enterprise transition mode и Transition Disable indication.
Разрешения на использование Bluetooth. Android 12 включает несколько новых разрешений для работы с Bluetooth:
BLUETOOTH_SCAN
— возможность поиска новых устройств и подключения к ним;BLUETOOTH_ADVERTISE
— разрешение на использование Bluetooth advertising;BLUETOOTH_CONNECT
— возможность подключения к привязанным устройствам.Эти разрешения заменяют ранее применявшиеся разрешения BLUETOOTH
и BLUETOOTH_ADMIN
, но только для приложений, собранных под Android 12. Старые приложения продолжат работать как прежде.
Индикаторы камеры и микрофона. Как и iOS, начиная с 12-й версии Android будет показывать индикаторы использования микрофона и камеры в правом верхнем углу экрана.
How Android Wallpaper Images Can Threaten Your Privacy — занимательная статья о том, как идентифицировать любое устройство с Android по установленным на экране обоям.
Небольшое предисловие. Еще в Android 2.0 появился класс WallpaperManager
, который можно использовать для управления установленными на экране обоями. Помимо прочего, класс включает метод getDrawable(
, который позволяет получить текущие обои в виде изображения. По факту это была уязвимость, которую исправили только в Android 8.1, заставив приложения использовать разрешение READ_EXTERNAL_STORAGE
, чтобы получить обои.
В той же Android 8.1 у класса WallpaperManager
появился другой метод — getWallpaperColors(
, позволяющий извлечь три «главных» цвета из обоев (именно его использует новая система теминга Android 12). Внутри эта функция использует метод k-средних, интересная особенность которого в том, что фактически он создает уникальный «цветовой отпечаток» обоев. В итоге по такому отпечатку можно точно идентифицировать устройство.
Для демонстрации этой техники автор создал приложение и выложил его исходники на GitHub.
Effective Kotlin Item 47: Avoid unnecessary object creation — статья о том, как сделать приложение чуточку быстрее, избавившись от ненужного создания дополнительных объектов.
Основная идея: объекты — дорогое удовольствие. Они занимают память, а на их создание уходит хоть и совсем незначительное по современным меркам, но время. Поэтому даже виртуальная машина Java старается минимизировать создание дополнительных объектов. Например, можно было бы подумать, что две следующие строки должны быть разными объектами, но это не так (оператор ===
сравнивает ссылки на объект):
val str1 = "Lorem ipsum dolor sit amet"
val str2 = "Lorem ipsum dolor sit amet"
print(str1 == str2) // True
print(str1 === str2) // True
Виртуальная машина, видя два одинаковых объекта типа String, объединяет их в один объект. То же самое происходит с типами Int
и Long
, но только для чисел от –128 до 127:
val i1: Int? = 1
val i2: Int? = 1
print(i1 == i2) // True
print(i1 === i2) // True
Для хранения каждого объекта используется заголовок из 12 байт, который на 64-битных системах выравнен по 8 байтам. Так что в целом заголовок занимает 16 байт, плюс сама ссылка на объект. Это не так много, но, когда имеешь дело с большим количеством одинаковых небольших объектов, это играет свою роль. Например, Array<
будет занимать в пять раз больше места, чем IntArray
, просто потому, что в первом случае каждое число обернуто в объект.
На создание объектов также уходит время. Оно совсем небольшое при создании одиночных объектов, но может иметь серьезные негативные последствия, когда объектов много. Например:
class A
private val a = A()
// Benchmark result: 2.698 ns/op
fun accessA(blackhole: Blackhole) {
blackhole.consume(a)
}
// Benchmark result: 3.814 ns/op
fun createA(blackhole: Blackhole) {
blackhole.consume(A())
}
// Benchmark result: 3828.540 ns/op
fun createListAccessA(blackhole: Blackhole) {
blackhole.consume(List(1000) { a })
}
// Benchmark result: 5322.857 ns/op
fun createListCreateA(blackhole: Blackhole) {
blackhole.consume(List(1000) { A() })
}
Есть несколько способов избежать создания объектов. Один из них — использовать синглтоны. Например, в следующей реализации связного списка объект класса Empty создается при каждом создании списка, хотя он всегда один и тот же:
sealed class LinkedList<T>
class Node<T>(
val head: T,
val tail: LinkedList<T>
) : LinkedList<T>()
class Empty<T> : LinkedList<T>()
// Usage
val list: LinkedList<Int> =
Node(1, Node(2, Node(3, Empty())))
val list2: LinkedList<String> =
Node("A", Node("B", Empty()))
Просто заменим его синглтоном:
object Empty : LinkedList<Nothing>()
Еще один способ — использовать пул объектов. Так делает, например, библиотека поддержки корутин. Вместо создания потока для каждой фоновой задачи она поддерживает пул (по сути, массив) потоков и запускает код на уже подготовленном потоке. Простейшая реализация пула может выглядеть примерно так:
private val connections: MutableMap<String, Connection> =
mutableMapOf<String, Connection>()
fun getConnection(host: String) =
connections.getOrPut(host) { createConnection(host) }
|
|