Премиум каналы

Javanese Online

**Описание на 450 символов для Telegram канала "Javanese Online":** Добро пожаловать в канал "Javanese Online"! Здесь вы найдете самые интересные статьи, новости, наблюдения и советы, связанные с языком программирования Java. Мы постоянно обновляем канал, чтобы предоставить вам актуальную информацию о последних тенденциях и разработках в мире Java. Независимо от вашего уровня опыта, вы найдете полезные материалы, которые помогут вам расширить свои знания и навыки в программировании на Java. Мы стремимся создать сообщество, где вы сможете обмениваться своими идеями, задавать вопросы и получать ответы от опытных профессионалов. Присоединяйтесь к "Javanese Online", чтобы оставаться в курсе последних новостей и развиваться вместе с нами в мире Java!

Последние публикации с канала

Информационная политика наносит ответный кусь

1. Сотрудник компании А делает доклад о технологии Х. Она новая, очень интересная и многообещающая.
2. Сотрудники-энтузиасты компаний Бэ, Цэ и Дэ заинтересовываются технологией Х, выясняют, в каких ещё нишах её можно применить, и оформляют результаты в виде докладов на конференциях, митапах и стримах.
3. Обыкновенные работяги замечают волну интереса и делают пет-проекты с использованием технологии Х. Рынок наводняется специалистами, которые умеют и хотят использовать именно эту технологию.
4. Компании А, Бэ, Цэ, Дэ, а также невинные жертвы Йе и Эф вынуждены переписать всё на технологию Х, чтобы заинтересовывать и нанимать разработчиков.

5. Появляется технология Игрек. Сотрудник компании Бэ загорается энтузиазмом и делает доклад…

К слову, https://www.joelonsoftware.com/2002/01/06/fire-and-motion/

Joel on Software
Fire And Motion

Sometimes I just can’t get anything done. Sure, I come into the office, putter around, check my email every ten seconds, read the web, even do a few brainless tasks like paying the American E…

08.04.2024 / 13:04

Нашёл детальную обучалку по Jetpack!
https://youtu.be/X9Rlst9NG5E?t=702

01.04.2024 / 09:04

Об устройстве Gravity

Начнём с определения: грава эт короч в какую сторону вьюха липнет гравити описывает способ размещения одного прямоугольника внутри другого.

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

Для начала, задано две оси: на какую сам сядешь, на какую джуна посадишь?

public static final int AXIS_X_SHIFT = 0;
public static final int AXIS_Y_SHIFT = 4;

таким образом, флаги для обеих запечатываются в младший байт в форме 0bYYYYXXXX.

В каждой половинке размещается по четыре флага:
0001) указана ли вообще гравити для этой оси (экзотика)
0010) привязываться ли к началу оси
0100) привязываться ли к концу оси
1000) обрезать ли слишком большой прямоугольник
public static final int AXIS_SPECIFIED = 0x0001;
public static final int AXIS_PULL_BEFORE = 0x0002;
public static final int AXIS_PULL_AFTER = 0x0004;
public static final int AXIS_CLIP = 0x0008;


Основные значения гравити формулируются таким образом:
LEFT — липнуть к началу оси X,
RIGHT — липнуть к концу оси X,
TOP — к началу Y,
BOTTOM — к концу Y.
Одна константа для примера:
public static final int TOP =
(AXIS_PULL_BEFORE|AXIS_SPECIFIED)<<AXIS_Y_SHIFT;


У CENTER в жизни отсутствует стремление к какой бы то ни было оси, FILL же склоняется к обеим. На примере горизонтали:
public static final int CENTER_HORIZONTAL =
AXIS_SPECIFIED<<AXIS_X_SHIFT;
public static final int FILL_HORIZONTAL =
LEFT|RIGHT;


Для тех, кто впервые видит FILL, есть ещё один сюрприз:
public static final int CLIP_HORIZONTAL =
AXIS_CLIP<<AXIS_X_SHIFT;

Это размещение по центру с обрезкой краёв.
Если скомбинировать это значение, например, с LEFT, то размещение будет уже слева, с обрезкой правого края.

FILL и CLIP по обеим осям просто содержат оба набора флагов:
public static final int CENTER =
CENTER_VERTICAL|CENTER_HORIZONTAL;
public static final int FILL =
FILL_VERTICAL|FILL_HORIZONTAL;

(Бесполезный факт: CENTER_VERTICAL == CENTER_HORIZONTAL>>AXIS_X_SHIFT<<AXIS_Y_SHIFT и наоборот, и так далее, и тому подобное.)

Остались START и END — начало и конец строки с учётом направления письма. Нет, прости, шупай, татэгаки и сероссыги, но это работает только по горизонтали.
Получается добавлением к LEFT и RIGHT флажка «ось X задана относительно layout direction»:
public static final int RELATIVE_LAYOUT_DIRECTION =
0x00800000;
public static final int START =
RELATIVE_LAYOUT_DIRECTION | LEFT;


Итого:
struct Gravity {
relative: bool,
axisX: AxisGravity,
axisY: AxisGravity,
}
struct AxisGravity {
specified: bool,
pullBefore: bool,
pullAfter: bool,
clip: bool,
}


Здесь я не упоминаю про флаги DISPLAY_CLIP, потому что обычно оно не надо.

В классе Gravity есть методы apply, которые разбирают этот набор флагов и выполняют размещение — в простых случаях этого хватает с головой.

Для случаев, когда нужно потрогать гравити самостоятельно — наконец-то, раздел с практическими советами!

1. Фильтруем входные данные линтом. @Gravity.GravityFlags недоступен, да и DISPLAY_CLIP из него нам не нужóн — но можно пойти и объявить собственный набор разрешённых флагов:
@IntDef(flag = true, value = {
FILL, FILL_HORIZONTAL, FILL_VERTICAL,
START, END, LEFT, RIGHT, TOP, BOTTOM,
CENTER, CENTER_HORIZONTAL, CENTER_VERTICAL,
CLIP_HORIZONTAL, CLIP_VERTICAL,
})
public @interface GravityFlags {}


2. Иногда нужно просто выбрать сторону, поэтому недавно у меня появилось такое:
@IntDef({ START, END, LEFT, RIGHT, TOP, BOTTOM })
public @interface SideGravity { }


3. Потенциально относительную граву можно легко превратить в абсолютную посредством Gravity.getAbsoluteGravity(gravity, layoutDirection). Тогда, например, @SideGravity сузится до простого набора { LEFT, TOP, RIGHT, BOTTOM }.
Нет, можно, конечно, написать
sealed class Gravity {
sealed class Absolute : Gravity()
sealed class Relative : Gravity() {
abstract fun absolute(dir: Int): Absolute
}
object ...
}

Это будет корректно и безопасно. Но громоздко и лень!

05.03.2024 / 11:03

:slowpoke: шикарный доклад про нутрянку корутин и способы их применения помимо асинхронности.

🟢 Разбор примитивов корутин из Kotlin stdlib
🟢 Как устроены билдеры вида sequence { yield() }
🟢 Глубокая рекурсия без отрыва стека
🟢 Парсеры

Friendly reminder разработчикам Kotlin:
⚫️ сиквенс — это бесполезная обёртка над итератором (в Rust её нет — компилятору легче оптимизировать и разворачивать длинные конструкции вида iter.map.filter.etc)
⚫️ DeepRecursiveScope.callRecursive стоило бы назвать invokeRecursive, консистентно с invoke и invokeSuspend, зашитыми в язык
⚫️ в очередной раз не хватает «:: наоборот» — fun smth() by DeepRecursiveFunction {}
Friendly reminder автору:
🟡 скоуп билдера должен быть @RestrictsSuspension
🟡 пожалуйста, не надо data-классов
Friendly reminder для организаторов:
💡 существуют нейросеточные плагины для убирания чвякания из речи

YouTube
Coroutines Beyond Concurrency by Alex Semin

Recording brought to you by American Express. https://americanexpress.io/kotlin-jobs

Kotlin coroutines are most known as an elegant and modern solution for managing asynchronous work. But due to their versatile design, coroutines can also be helpful for…

02.02.2024 / 09:02

Year::<init>(😘)

31.12.2023 / 21:12

Как передать любой View произвольный AttributeSet

А зачем?
Есть атрибуты, которые можно выставить только из XML. Но не все вью удобно инстанцировать из XML, особенно когда это анонимный класс: addView(object : SomeView(context) { /* тут какие-то оверрайды */ }).

Сразу расстрою: программно создать AttributeSet, который будет работать с obtainStyledAttributes, не получится, если не прибегать к приватным API андроида.
В этом месте я и прекратил свои поиски, когда в 2016 начал верстать из кода.

Но можно любой вьюшке навязать атрибуты из layout-файла.
Например, такого:

<?xml version="1.0" encoding="utf-8"?>
<View
xmlns:android="http://schemas.android.com/apk/res/android"
android:scrollbars="horizontal" />


Теперь парсим XML, пропускаем открывающий тэг и забираем атрибуты:
val parser = resources.getLayout(R.layout.scrollbars)
val attrs = Xml.asAttributeSet(parser)
advanceToRootNode(parser)
addView(object : SomeView(context, attrs) { /* тут какие-то оверрайды */ })
parser.close()


Исходник LayoutInflater::advanceToRootNode().

GitHub
platform_frameworks_base/core/java/android/view/LayoutInflater.java at ac5f755472e02f039f947ccfd5f5282e0ac80fe3 · aosp-mirror/…

Contribute to aosp-mirror/platform_frameworks_base development by creating an account on GitHub.

08.12.2023 / 18:12

Телефон как USB-хаб с периферией

Когда-то давно мне срочно понадобился микрофон. Он есть в телефоне, но не было в компьютере. Накопал тогда mic over mumble, который после долгих уговоров заработал. Микрофон я потом купил, а потом ещё один 😌

Когда я ходил на стрим к Кириллу, он мне рассказал про Iriun webcam — приложение, которое пробрасывает камеру телефона на компьютер. Очень правильная штука, потому что в телефонах сейчас хорошие камеры, а веб-камера и телефон одновременно использовать мне не нужно.

Пробросить экран телефона можно с помощью scrcpy.

А почему так сложно? Я могу в настройках раздать вайфай, могу использовать телефон как USB-модем. Могу включить передачу файлов, отдав флешку в распоряжение компьютера.
Где тогда переключатель, который превратит телефон в веб-камеру и USB-микрофон? Удивительно, что это нужно как-то отдельно прокидывать через adb или Wi-Fi с помощью стороннего софта. Хочется, чтобы эти возможности были доступны не только гикам, но и бабушкам из глубинки.

И ещё: во всех мессенджерах можно показать экран, то есть пробросить сигнал с выхода на вход. Но почему нельзя пошарить выход аудиокарты? Хочу поставить музычку своим собеседникам!

21.11.2023 / 12:11

Раздельная компиляция, min, compile, target

В целом Java-технологии привычные к раздельной компиляции. Серверные приложения компилируются с Java Class Library, которая подкладывается в compile classpath при сборке, а запускаются с другим экземпляром JCL, которая лежит на сервере.

Однако, эта раздельность почти не чувствуется. Она незримо присутствует и заключается в том, что в итоговом jar у нас не лежит весь java.lang, java.util и что мы там ещё любим. Мы запускаем приложение с той же версией JDK, с которой собирали, и всё просто работает.

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

В desktop-приложениях (кто-то их ещё пишет?) всё ещё проще: зачастую JVM приносят с собой, и раздельной компиляции как не бывало.

В Android же, как известно, зоопарк: на конечных устройствах много разных версий. И вот тут система сборки спроектирована очень удачно:
• compile SDK — последняя версия, известная разработчику приложения на момент сборки. Она подкладывается в compile classpath, за счёт чего разработчик видит все новые фичи платформы;
• min SDK — минимальная поддерживаемая версия. Старой платформе, которую разработчик не хочет поддерживать, позволяет отклонять установку приложений. Инструментарию позволяет подсказать программисту, что те или иные declarations недоступны в min и могут отсутствовать в runtime classpath, поэтому нужно обернуть их использование в if;
• target SDK — версия, на поведение которой рассчитывает приложение. Позволяет более новой версии платформы сохранить поведение старой в старом приложении.

Таким образом, в быстро меняющемся мире Android-приложение компилируется для свежей версии платформы (compile SDK), ифами поддерживает более старые версии (вплоть до min SDK), а платформа, если она новее, чем ожидаемая (target SDK), сохраняет старое совместимое поведение (тоже ифами).

Это прекрасно. Это шедевр.

Для сравнения, ситуация в мире плагинов для IntelliJ: выбираешь одну версию, которая и будет твоим compile и min. Хочешь поддержать постарше — опускаешь версию, перестаёшь видеть новые declarations. Если в новых версиях что-то deprecated — ты об этом узнаешь на этапе валидации плагина, где-то после компиляции и упаковки.

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

Зависишь от других плагинов? Вообще страдай. Там может быть установлена любая версия. Например, если зависишь от Android-плагина для IDE, то при компиляции видишь версию, которой полгода, а в бетах Android Studio уже много раз переименовали классы, поменяли на интерфейсы, переместили в другой пакет. (И сделали это в стенах той же компании, где придумали min, compile, target.) Удачи!

17.10.2023 / 11:10

Размножение массивов

String::repeatпроизведение искусства.

Arrays.fill же написан банально и буднично, но я подозреваю, что он успешно векторизуется.

03.10.2023 / 14:10

Пару слов про зерокодинг и ни одной шутки про зерозарплатинг

Да, из готовых компонентов можно собрать сайт, приложение или круд. Оно даже будет работать. Я смотрю на это просто как на программирование на более высоком уровне.

Что здесь примечательно для нас, разработчиков? А то, что компоненты «среднего» уровня написаны такими же программистами. И если менеджер мышкой натыкивает приложение быстрее, чем профессиональный разработчик, то у нас, коллеги, наблюдается проблема с job security качеством и доступностью компонентов. Если OAuth из конструктора интегрируется быстрее и работает лучше, чем решение с гитхаба, значит, мы залайкали не тот репозиторий, автор его недодокументировал или вообще бросил на полпути. Если нам данные приходят по одной схеме, и мы, чтобы трансформировать их в другую, удобную нам, выражаем обе через ДТОшки и пишем маппер между ними, значит, библиотека, которой мы намазываем данные на классы, не решает нашу задачу. Если прокладка для работы с БД заставляет нас… ну и так далее.

Зерокодинг никогда не станет мощнее и гибче, чем «настоящее» программирование. А наша задача — делать так, чтобы последнее не отставало по скорости и качеству. Хочу надеяться, что конкуренция со стороны зерокодинга поспособствует повышению качества нашего родного программирования.

06.09.2023 / 07:09

Один мой коллега постоянно забывал, как кого зовут, из-за чего в нашем лексиконе появились два собирательных персонажа — Кирилл Гладков и Алексей Розов.
Дошутились таки!

Telegram
Mobile Developer

Очень важный анонс! 🔥🔥
Mobile Developer и Android Broadcast идут в оффлайн!

После нашего с Кириллом турне по России мы поняли, что во многих городах есть люди, которые хотели бы встречаться, общаться и обмениваться знаниями без деления на платформы, а просто…

05.09.2023 / 11:09

Если вы когда-нибудь искали способ поставить бряку для одного конкретного экземпляра, то… вот он!

29.08.2023 / 11:08

Привет, я подсяду? Поговорим о корпоративной коррупции?

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

Теперь давайте прикола ради глянем библиотеку, которая не работает: она должна помогать следить за внешним видом приложения, но даже стандартную кнопочку со стандартным stateListAnimator'ом в дефолтной теме скриншотит неправильно, не говоря уже про скруглённые аватарки, которые у них в собственном приложении таки есть, судя по нагугленным скриншотам.

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

Ах да. PixelCopy.request. Шах и мат, аферисты.

GitHub
View clipping to outline doesn't work on screenshots · Issue #276 · facebook/screenshot-tests-for-android

When make a screenshot test for some layout, and some custom view inside contains outline clipping like that: view.outlineProvider = object : ViewOutlineProvider() { override fun getOutline(v: View...

16.08.2023 / 12:08

По-явански:

IllegalStateException: cannot make a new request because the previous response is still open: please call response.close() Занятный крэш меня сегодня посетил. Типовое обновление токена. Нетрудно понять, где именно баг, но как именно вы бы его чинили?

ой

04.08.2023 / 20:08

Редактируемый списокEditText внутри RecyclerView

Очень много лулзов на StackOverflow по этому вопросу. Написать адаптер с эдиттекстами под силу каждому, а вот получить назад отредактированные данные могут не только лишь все.

Рассмотрим для начала очевидно нерабочий способ: for-each по вьюшечкам. Как ни странно, я видел такое решение в продакшене. Чтобы оно работало, ресайклер был завёрнут в скроллвью!

Следующий сомнительный вариант: нацепить TextWatcher и записывать результат Editable.toString() на каждый тык пользователя по клавиатуре.

Название Editable, кстати, намекает нам на мутабельность редактируемого буфера. Так возникает ещё одна стратегия — дёрнуть Editable getText(), а не слушать каждое изменение. Тогда байндинг будет выглядеть так:
editText.setText(editables[position] ?: strings[position])
editables[position] = editText.text

EditText создаст мутабельную копию строки. А можно сделать это самостоятельно, потому что в editables уже может лежать нужный буфер. Только нужно отвадить EditText от копирования, заменив Editable.Factory.
Итоговый gist и ответ на SO.

Gist
Another approach to EditTexts inside RecyclerView

Another approach to EditTexts inside RecyclerView. GitHub Gist: instantly share code, notes, and snippets.

10.07.2023 / 08:07

Недавно меня посетила красивая #идея — вот бы приложения карт умели показывать слои, предоставленные другими приложениями! Открываешь Organic, 2GIS или что там сейчас есть из картографии — а туда сразу подтягиваются такси, самокаты, каршеринг, общественный транспорт, парковки — в зависимости от того, какие провайдеры установлены. Философия UNIX во всей красе.

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

04.06.2023 / 19:06

Интерфейсы коллекций

Вчера задали мне этот вопрос на собесе. Ну я и перечисляю: Iterable, Collection, List, Set, SortedSet, NavigableSet, Queue, Deque; Map, ConcurrentMap — тут остановился в ожидании реакции собеседующего. Глазами хлопаю, мол, что, надо ещё?

Оказывается, это почти всё. Для пущего эффекта можно выучить: BlockingQueue, TransferQueue, BlockingDeque; SortedMap, NavigableMap, ConcurrentNavigableMap.

03.06.2023 / 17:06

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

Пример
KEEP — за ссылку спасибо @r4zzz4k

17.05.2023 / 11:05

Forwarded From Android Broadcast (Кирилл Розов)

🔴 Стартует собеседование в прямом эфире

Проводит Михаил Горюнов @Harmonizr, разработчик Android-приложений, библиотек и инструментов.

Миша будет собеседовать на позицию Android разработчика без уровня (требования здесь)

P.S. Запись останется на канале

#AndroidBroadcast #собеседование

04.05.2023 / 15:05

Парсинг ботокоманд

/add_thing Name Description
/add_thing Name 'Long description'

Как распарсить эти команды и не сойти с ума? Внутри JDK периодически используется StringTokenizer, но это просто String.split() образца 1995 года. А нужный класс, который понимает кавычки, называется StreamTokenizer, и, как следует из названия, он ещё и стрим разобрать может.

25.04.2023 / 11:04
Отзывы: - 0
Поделитесь вашим мнением! Оставьте отзыв:

Похожие

Избранное