Android Broadcast – Telegram
Android Broadcast
14.4K subscribers
3.68K photos
368 videos
11 files
6.1K links
Подборка новостей и статей для Android разработчиков.

Реклама и связь с автором @ab_manager

РКН https://abdev.by/rkn_tg_ab #MQRZR
Download Telegram
Большинство современных проектов используют RxJava либо Kotlin Coroutines.

Знаете ли вы разницу между Schedulers.computations() и Schedulers.io()? Между Dispatchers.Default и Dispatchers.IO? Чур документацией не пользоваться!
Final Results
52%
Да
39%
Нет
9%
Не пользуюсь Rx и корутинами
#Rx #Coroutines #Concurrency

Understanding CPU- and I/O-bound for asynchronous operations

В современных приложениях мы выносим обработку долгих операций на фоновые потоки. Знаете ли Вы какие операции надо запускать на этих пулах потоков, а самое главное почему? Почему не использовать единый пул для всех фоновых операций? Зачем в Kotlin Coroutines и RxJava есть понятия I/O-bound и CPU-bound.

Причиной этому является как I/O операции ведут себя по сравнению к CPU интенсивным операция. Чтение данных из файлов, потоков, сокетов или сети часто содержит много ожидания: подключение к источнику, дождаться ответа и только потом идет его реальная передача, которая может также приостанавливаться из-за низкой скорости или загруженности. Операции не связанные с чтение не из оперативной памяти вызывают IOwait - системный вызов, который сообщает процессору о необходимости приостановить выполнение текущего потока, пока данные станут доступны или будут успешно переданы.

Важно помнить, что потоки, выполняющие I/O операции, проводят значительную часть времени в ожидании. При маленьком пуле потоков, выделенных для таких операций у вас может быть простой приложения.

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

Подведя итоги описанной выше разницы работы задача с IO и CPU можно понять что:
👉 CPU и I/O операции стоит выполнять в разных пулах потоков
👉 пул для CPU интенсивных операций должен опираться на количество ядер в устройстве и не превышать его
👉 пул для I/O операций может быть довольно большим

Рассмотрим пример:
1️⃣ Скачаем картинку из сети
2️⃣ Сделаем ей blur
3️⃣ Отобразим ее на устройстве

Мы имеем 3 разных пула, которы надо использовать:
1️⃣ I/O
2️⃣ CPU
3️⃣ Main

Реализация примера на корутинах:
launch(Dispatchers.IO) {
val image = api.fetchImageAsync(url).await()
val blurred =withContext(Dispatchers.Default) {
image.blur()

}
withContext(Dispatchers.Main) {
displayImage(blurred)
}
}

Реализация на RxJava:

api.fetchImageObservable(url)
.subscribeOn(Schedulers.io()
.observeOn(Schedulers.computation())
.map { blurImageSync(it) }
.observeOn(AndroidSchedulers.mainThread())
.subscribe { displayImage(it) }

В дополнение можно сказать что Coroutine выигрывают еще в том что они не блокируют потоки и позволяют во время ожидания выполняться на них других операциям, что позволяет более эффективно использовать пулл I/O.
#NIO #IOwait

Как решение IOwait можно использовать неблокирующее APO - Java NIO (New I/O), которое использует специальные системные вызовы, которые не блокирует поток при выполнение некоторых I/O операций.
#Library #Network #Socket #NIO

AsyncSocket - Asynchronous socket (client+server) continues communications

Библиотека, которая простит ваще взаимодействие с сокетами и сделает это эффективно. Она построен на основе Java NIO API, что позволяет выполнять ей I/O операции неблокирующим потоки способом.
#Gradle #Jetifier #AndroidX

can-i-drop-jetifier Gradle Plugin

Вы уже перешли в своем проекте с Android Support Library (ASL) на AndroidX? Но вот в чем загвоздка - не все авторы библиотек сделали тоже самое, поэтому вам в код тянутся зависимости ASL.

Решить эту проблему призвана утилита Jetifier от Google. Она превращает старый ASL код в новый AndroidX, но на такую модификацию байткода требуется время. Но если в вашем проекте уже нет ASL библиотек. то лучше отключить Jetifier.

Плагин позволяет определить какие из библиотек используют ASL Просто выполните:

./gradlew -Pandroid.enableJetifier=false canIDropJetifier

Отключение Jetifier для запуска таска - обязательно
#Kotlin

@JvmOverloads for Android Views

Подробный рассказ о том как для Kotlin функций и конструкторов с аргументами по умолчанию обеспечивать корректную работу на Android на пример собственных View и аннотации @JvmOverloads.
Если выполнить launch(Dispatchers.Main) на Main потоке, то в каком порядке будет выполнятсья ваш код?
Final Results
0%
Запуститься сразу
100%
Будет исполнен как освободиться Main поток
0%
Зависит от других условий
Правильный ответ - "Будет исполнен как освободиться Main поток"

Если выполнить код
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState
launch(Dispatchers.Main) {
log("A")
}
log("B")
}
В логах вы увидите: BA
#Kotlin #Coroutines

Launching a Kotlin Coroutine for immediate execution on the Main thread

Как можно сделать так, чтобы при запуске корутины на текущем потоке происходил ее мгновенный запуск? CoroutineDispatcher отвечает за поток, который будет выполнять код внутри корутины, есть метод isDispatchNeeded(), который возвращает true если выполнение должно продолжиться на другом потоке. Большинство CoroutineDispatcher возвращают true. Но для Dispatchers.Main потока будет эффективнее исполнять код сразу же если запуск корутины происходит с Main потока.

В API Coroutine вы можете найти интересный элемент Dispatchers.Main.immediate, который выполняет Coroutine мгновенно, когда она находится в том же контексте. Запустив код из предыдущего с Dispatchers.Main.immediate поста мы уже видим вывод: AB. Дилемма решена
#Kotlin #MemoryLeak

How Kotlin helps you avoid memory leaks

Kotlin ввел множество новых механизмов, которые упрощают написание кода в Android:
👉 null safety
👉 type inference
👉 закрытые от наследования классы по умолчанию
👉 все вложенные классы по умолчанию статические

Но в дополнение ко всем ещё Kotlin может помогать вам избегать утечек памяти.

class SampleActivity : Activity() {

override fun onCreate(savedState: Bundle?) {
super.onCreate(savedState)
setContentView(R.layout.activity_leak)
button.setOnClickListener {
startAsyncWork()
}
}

private fun startAsyncWork() {
val work = Runnable {
SystemClock.sleep(20000)
}
Thread(work).start()
}
}

Такой код не вызовет утечки в Android, хотя его аналог в Java бы вызывал.

Разница заключается в том, что лямбда в Kotlin интерпретируется как статический вложенный класс, и не хранит ссылку на внешний класс, если код внутри не обращается к внешним нестатическим элементам. В Java независимо от каких-либо условий всегда будет создаваться обычный класс.

Замечание: вышеприведенное рассматривается для Java 7, так как Android разработка сейчас использует эту версию в байт коде. Для Java 8 лямбды исполняются с помощью invokedynamic, что оптимизирует их выполнение.
#JakeWharton #R8 #Optimizations

R8 Optimization: Class Constant Operations

Продолжение серии статей о оптимизация кода, которые реализованы в R8 от Jake Wharton. В новой статье рассказывается о оптимизации констант классов.

Рассмотрим частый пример классов в константах:
private static final String TAG = "MyClass";
// or
private static final String TAG =
MyClass.class.getSimpleName();

Такие константы очень часто используются для логирования. Если рассмотреть после компиляции кода, то MyClass.class.getSimpleName() всегда будет возвращать одно и тоже значение - "MyClass". Фактически в оптимизированном байткоде можно делать подмену выполнения метода на простую строку. Важно понимать что это не работает для случая getClass().getSimpleName(), т.е. когда класс получается динамически.

R8 получила такую оптимизацию кода и теперь неважно как вы будете создать LOG_TAG для ваших логов 🎉

Android Studio 3.4 уже на подходе и R8 становится инструментом по умолчанию для оптимизации кода в ней.
#AndroidX #WorkManager

Android Jetpack WorkManager Stable Release

То чего так долго ждали свершилось WorkManager 1.0 Stable!

Ключевые функции WorkManager
👉 Возможность задания ограничений для выполнения задач, например необходимость выполнить когда есть подключение к сети и устройство заряжается
👉 Поддержка одноразовых и периодических задач
👉 Поддержка цепочек задач с входными и выходными данными
👉 Гарантирует выполнение задач, даже после перезагрузки устройства
👉 Поддержка Android 4.0+ (API 14+)
👉 Использует JobScheduler API на Android 6.0+ (API 23+) и комбинацию AlarmManager и BroadcastReceiver на более ранних версиях.
👍1
С чего начать использование?

1️⃣ Подключить зависимости

dependencies {
def work_version = 1.0.0

// Java
implementation
"android.arch.work:work-runtime:$work_version"

// Kotlin KTX + coroutines
implementation
"android.arch.work:work-runtime-ktx:$work_version"
}

2️⃣ Создать Worker, который будет выполнять задачу

class MyWorker(
ctx: Context,params: WorkerParameters
): Worker(ctx, params) {

override fun WorkerResult doWork() {
//do the work you want done in the background
return Result.success()
}
}  

3️⃣ Создайте Constraints для задачи (опционально)

val constraints: Constraints = Constraints.Builder()
.setRequiresCharging(true)
.setRequiredNetworkType(NetworkType.CONNECTED)
.build()

4️⃣ Создайте задачу

val myWork =
OneTimeWorkRequestBuilder<MyWorker>()
.setConstraints(constraints).build()

5️⃣ Добавьте ее на выполнение

WorkManager.getInstance().enqueue(myWork)
#Kotlin #KtAcademy

The beauty of Kotlin typing system от Marcin Moskala@Kt.Academy

Рассказ о прекрасно спроектированной системе типов в Kotlin, которая предоставляет удобный способ для работы с nullability, type inference и др.

В статье рассказывается о
👉 Тип Any? - супертип всех типов
👉 Тип Unit
👉 Тип Nothing - подтип всех типов
👉 Какой тип у null
👍1
Пример иерархии типов в Kotlin
#LibUpdate #JakeWharton

ThreeTebABP 1.2.0

Вышел новый релиз библиотеки ThreeTebABP, который добавил возможность загружать базу данных часовых поясов, расположенных в asset-ах
👍1
#Kotlin

When You Should Use Null in Kotlin

Является ли значение null проблемой и стоит ли избегать его использования? Например, я видел что разработчики используют пустые строки как значения переменных типа String, которые не проинициализированы.

К сожалению, репутация null испорчена системой типов в Java, частые NPE и множество if (value != null). null - это хороший выбор для представления состояния, когда у вас не проинициализрован объект, либо не доступен в текущий момент.

Для того чтобы ваше работы с null не приводила к ошибкам в Kotlin было сделано множество средств:
👉 система типов, различающая nullable и non-nullable типы
👉 безопасные вызовы ( ?. )
👉 безопасные приведения ( as? )
👉 else shorthand ( ?: )
👉 неизменяемые переменные

Язык должен помогать вам писать код как это логически правильно и не заставлять использовать что-то из-за своих ограничений. Kotlin старается соответствовать этим ожиданиям и у него это прекрасно получается!

Не бойтесь null, так в нем есть польза.
👍1
#AndroidLint #Performance #BestPractices #CodeQuality

Android Lint Performance Tips

Android Lint - это замечательный анализатор кода, который определяет специфичные для Android баги и потенциальные проблемы. Расстраивает его невысокая скорость работы, которая становиться хуже с каждым релизом 😪

Как ее увеличить читайте в статье из обсуждений о производительности Lint из Google Groups.

Замечание: Информации много и я не смог ее уместить в небольшой пост, поэтому чтобы не захламлять канал я вынес статью.
👍1