en
Feedback
Javanese Online

Javanese Online

Open in Telegram

Статьи и новости, наблюдения и советы. Кодревью: http://javanese.online/%D1%80%D0%B0%D0%B7%D0%B1%D0%BE%D1%80_%D0%BA%D0%BE%D0%B4%D0%B0/ Обсуждение в @javanese_questions Материалы пишет @Harmonizr

Show more
723
Subscribers
No data24 hours
+37 days
+530 days

Data loading in progress...

Tags Cloud
No data
Any problems? Please refresh the page or contact our support manager.
Incoming and Outgoing Mentions
---
---
---
---
---
---
Attracting Subscribers
December '24
December '24
+5
in 0 channels
November '24
+21
in 0 channels
Get PRO
October '24
+34
in 0 channels
Get PRO
September '24
+7
in 0 channels
Get PRO
August '24
+11
in 0 channels
Get PRO
July '24
+12
in 0 channels
Get PRO
June '24
+4
in 0 channels
Get PRO
May '24
+28
in 0 channels
Get PRO
April '240
in 0 channels
Get PRO
March '24
+58
in 0 channels
Get PRO
February '240
in 1 channels
Get PRO
January '240
in 0 channels
Get PRO
December '230
in 0 channels
Get PRO
November '23
+7
in 0 channels
Get PRO
October '23
+28
in 1 channels
Get PRO
September '23
+38
in 0 channels
Get PRO
August '23
+40
in 0 channels
Get PRO
July '23
+29
in 0 channels
Get PRO
June '23
+20
in 0 channels
Get PRO
May '23
+37
in 0 channels
Get PRO
April '23
+27
in 0 channels
Get PRO
March '23
+26
in 0 channels
Get PRO
February '23
+18
in 0 channels
Get PRO
January '23
+19
in 0 channels
Get PRO
December '22
+9
in 0 channels
Get PRO
November '22
+10
in 0 channels
Get PRO
October '22
+12
in 0 channels
Get PRO
September '22
+16
in 0 channels
Get PRO
August '22
+14
in 0 channels
Get PRO
July '22
+15
in 0 channels
Get PRO
June '22
+7
in 0 channels
Get PRO
May '22
+27
in 0 channels
Get PRO
April '22
+12
in 0 channels
Get PRO
March '22
+8
in 0 channels
Get PRO
February '22
+43
in 0 channels
Get PRO
January '22
+17
in 0 channels
Get PRO
December '21
+12
in 0 channels
Get PRO
November '21
+17
in 0 channels
Get PRO
October '21
+23
in 0 channels
Get PRO
September '21
+20
in 0 channels
Get PRO
August '21
+10
in 0 channels
Get PRO
July '21
+22
in 0 channels
Get PRO
June '21
+10
in 0 channels
Get PRO
May '21
+6
in 0 channels
Get PRO
April '21
+23
in 0 channels
Get PRO
March '21
+33
in 0 channels
Get PRO
February '21
+62
in 0 channels
Get PRO
January '21
+10
in 0 channels
Get PRO
December '20
+391
in 0 channels
Date
Subscriber Growth
Mentions
Channels
21 December0
20 December0
19 December0
18 December0
17 December+2
16 December+1
15 December0
14 December0
13 December0
12 December0
11 December0
10 December+1
09 December0
08 December0
07 December0
06 December0
05 December+1
04 December0
03 December0
02 December0
01 December0
Channel Posts
Раздельная компиляция, 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.) Удачи!

2
Раздельная компиляция, min, compile, target В целом Java-технологии привычные к раздельной компиляции. Серверные приложения компилируются с Java Class Library которая подкладывается в compile classpath при сборке, а запускаются с другим экземпляром JCL, которая лежит на сервере. Однако, эта раздельность почти не чувствуется. Она незримо присутствует и заключается в том, что в итоговом jar у нас не лежит весь java.lang, java.util и что мы там ещё любим. Мы запускаем приложение с той же версией JDK, с которой собирали, и всё просто работает. В desktop-приложениях (кто-то их ещё пишет?) всё ещё проще — зачастую JVM приносят с собой, и раздельной компиляции как не бывало. В Android же, как известно, зоопарк: на конечных устройствах много разных версий. И вот тут система сборки спроектирована очень удачно: • compile SDK — последняя версия, известная разработчику приложения на момент сборки. Она подкладывается в compile classpath, за счёт чего разработчик видит все новые фичи платформы.
1
3
Размножение массивов String::repeat — произведение искусства. Arrays.fill же написан банально и буднично, но я подозреваю, что он успешно векторизуется.
1 919
4
Пару слов про зерокодинг и ни одной шутки про зерозарплатинг Да, из готовых компонентов можно собрать сайт, приложение или круд. Оно даже будет работать. Я смотрю на это просто как на программирование на более высоком уровне. Что здесь примечательно для нас, разработчиков? А то, что компоненты «среднего» уровня написаны такими же программистами. И если менеджер мышкой натыкивает приложение быстрее, чем профессиональный разработчик, то у нас, коллеги, наблюдается проблема с job security качеством и доступностью компонентов. Если OAuth из конструктора интегрируется быстрее и работает лучше, чем решение с гитхаба, значит, мы залайкали не тот репозиторий, автор его недодокументировал или вообще бросил на полпути. Если нам данные приходят по одной схеме, и мы, чтобы трансформировать их в другую, удобную нам, выражаем обе через ДТОшки и пишем маппер между ними, значит, библиотека, которой мы намазываем данные на классы, не решает нашу задачу. Если прокладка для работы с БД заставляет нас… ну и так далее. Зерокодинг никогда не станет мощнее и гибче, чем «настоящее» программирование. А наша задача — делать так, чтобы последнее не отставало по скорости и качеству. Хочу надеяться, что конкуренция со стороны зерокодинга поспособствует повышению качества нашего родного программирования.
1 802
5
Один мой коллега постоянно забывал, как кого зовут, из-за чего в нашем лексиконе появились два собирательных персонажа — Кирилл Гладков и Алексей Розов. Дошутились таки!
871
6
Если вы когда-нибудь искали способ поставить бряку для одного конкретного экземпляра, то… вот он!
Если вы когда-нибудь искали способ поставить бряку для одного конкретного экземпляра, то… вот он!
519
7
Привет, я подсяду? Поговорим о корпоративной коррупции? Давайте разберёмся, как в опенсорс попадают всякие технологии. Вот мне кусочек рационального мышления подсказывает, что компания решает свои задачи, свои проблемы, выпускает что-то для себя, внедряет технологию в свои процессы, извлекает из этого коммерческую выгоду, и — почему бы нет — делится с другими, собирая багрепорты от широкой аудитории и повышая качество — а это снова выгода. Ну, логично, мне кажется. Вроде как-то так должно работать. Теперь давайте прикола ради глянем библиотеку, которая не работает: она должна помогать следить за внешним видом приложения, но даже стандартную кнопочку со стандартным stateListAnimator'ом в дефолтной теме скриншотит неправильно, не говоря уже про скруглённые аватарки, которые у них в собственном приложении таки есть, судя по нагугленным скриншотам. Чистая прибыль в 23 гигабакса даёт о себе знать, нужно срочно стартовать новый проект, обосновать его целесообразность, выбить финансирование. Написанный код потом можно выкинуть — не прижился. Ах да. PixelCopy.request. Шах и мат, аферисты.
471
8
ой
ой
472
9
Редактируемый список — 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.
424
10
Недавно меня посетила красивая #идея — вот бы приложения карт умели показывать слои, предоставленные другими приложениями! Открываешь Organic, 2GIS или что там сейчас есть из картографии — а туда сразу подтягиваются такси, самокаты, каршеринг, общественный транспорт, парковки — в зависимости от того, какие провайдеры установлены. Философия UNIX во всей красе. Как и большинство других идей, я не первый, к кому они приходят. Например, есть вот такая закрытая/коммерческая интеграция. А хочется — публичный интерфейс для всех.
379
11
Интерфейсы коллекций Вчера задали мне этот вопрос на собесе. Ну я и перечисляю: Iterable, Collection, List, Set, SortedSet, NavigableSet, Queue, Deque; Map, ConcurrentMap — тут остановился в ожидании реакции собеседующего. Глазами хлопаю, мол, что, надо ещё? Оказывается, это почти всё. Для пущего эффекта можно выучить: BlockingQueue, TransferQueue, BlockingDeque; SortedMap, NavigableMap, ConcurrentNavigableMap.
364
12
Опаньки, оказывается, из типового параметра можно убрать нуллабельность (подсветка синтаксиса тоже удивлена). Источник
Опаньки, оказывается, из типового параметра можно убрать нуллабельность (подсветка синтаксиса тоже удивлена). Источник
460
13
🔴 Стартует собеседование в прямом эфире Проводит Михаил Горюнов @Harmonizr, разработчик Android-приложений, библиотек и инст
🔴 Стартует собеседование в прямом эфире Проводит Михаил Горюнов @Harmonizr, разработчик Android-приложений, библиотек и инструментов. Миша будет собеседовать на позицию Android разработчика без уровня (требования здесь) P.S. Запись останется на канале #AndroidBroadcast #собеседование
273
14
🔴 Стартует собеседование в прямом эфире Проводи Михаила Горюнова @Harmonizr, разработчик Android-приложений, библиотек и инс
🔴 Стартует собеседование в прямом эфире Проводи Михаила Горюнова @Harmonizr, разработчик Android-приложений, библиотек и инструментов. Миша будет собеседовать на позицию Android разработчика без уровня (требования здесь) P.S. Запись останется на канале #AndroidBroadcast #собеседование
14
15
Парсинг ботокоманд /add_thing Name Description /add_thing Name 'Long description' Как распарсить эти команды и не сойти с ума+1
Парсинг ботокоманд /add_thing Name Description /add_thing Name 'Long description' Как распарсить эти команды и не сойти с ума? Внутри JDK периодически используется StringTokenizer, но это просто String.split() образца 1995 года. А нужный класс, который понимает кавычки, называется StreamTokenizer, и, как следует из названия, он ещё и стрим разобрать может.
360
16
Сбор заявок на участие в собеседовании Мы ищем кандидата, кто пройдет в прямом эфире собеседование на вакансию, идентичную ре
Сбор заявок на участие в собеседовании Мы ищем кандидата, кто пройдет в прямом эфире собеседование на вакансию, идентичную реальной, в прямом эфире у Михаила Горюнова @Harmonizr , разработчика Android-приложений, библиотек и инструментов. Миша будет собеседовать на позицию Android разработчика (речь не идет про уровень или года опыт), а с требованиями можно ознакомиться здесь   @android_broadcast #собеседование
209
17
Transient Iterator Что может выстрелить в этом кусочке кода: map.entries.toSet()? А вот что: entrySet().iterator().next() возвращает себя — этот же итератор, который впридачу реализовывает Map.Entry. В итоге из энтрей непустой Map всегда получается Set из единственного Entry. С одной стороны, это жёсткая подстава. С другой — экономный способ просмотреть любое количество элементов за константную память. Поэтому в тех местах, где это может быть полезно, я предоставляю оба варианта — «нормальный» итератор и «мимолётный». Так же можно поступить с итератором по строкам файла: не возбраняется фильтровать, искать префиксы или какие-то символы, а потом уже выгружать в память необходимое подмножество элементов.
406
18
Стрельба по-македонски на Java
341
19
Эффективное ООП Files.readAllLines(path).size Страшно? Жутко? Жизнь — боль? Вывод: это ваше ООП неэффективно, объекты нинужны, они только память тратят. Нужна функция file_count_lines(path)! абстракция либо неверно выбрана, либо коряво реализована. Рассмотрим оба варианта. Другая абстракция: Iterator<CharSequence> & Closeable. Файл проматывается по мере доступа к элементам. CharSequence можно выгрузить в память методом toString(), до этого он просто помнит отступ и длину в файле, а charAt() заглядывает в mmap. Некорявая реализация: List<CharSequence> & Closeable. Написать такой лист сильно сложнее, чем итератор, но нет ничего невозможного: • size при первом вызове проматывает файл и строит индекс — складывает позиции всех \n в массив интов — и возвращает его размер, • get(at) проматывает файл до нужного места, достраивая по пути индекс, если он неполный. Естественно, оба метода используют один и тот же индекс и умеют достраивать его по мере необходимости. Гипотетический Files.listOfLines(path).forEach() пробегает итератором по файлу ровно один раз. Самый тяжёлый сценарий, Files.listOfLines(path).map(CharSequence::toString), приведёт к накладным расходам в виде промежуточных CharSequence и индекса, но это копейки.
447
20
Приняв во внимание обратную связь сообщества, редакция приняля решение прекратить ведение канала на неопределённый срок.
320