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 more723
Subscribers
No data24 hours
+37 days
+530 days
Data loading in progress...
Similar Channels
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 December | 0 | |||
| 20 December | 0 | |||
| 19 December | 0 | |||
| 18 December | 0 | |||
| 17 December | +2 | |||
| 16 December | +1 | |||
| 15 December | 0 | |||
| 14 December | 0 | |||
| 13 December | 0 | |||
| 12 December | 0 | |||
| 11 December | 0 | |||
| 10 December | +1 | |||
| 09 December | 0 | |||
| 08 December | 0 | |||
| 07 December | 0 | |||
| 06 December | 0 | |||
| 05 December | +1 | |||
| 04 December | 0 | |||
| 03 December | 0 | |||
| 02 December | 0 | |||
| 01 December | 0 |
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-приложений, библиотек и инструментов.
Миша будет собеседовать на позицию Android разработчика без уровня (требования здесь)
P.S. Запись останется на канале
#AndroidBroadcast #собеседование | 273 |
| 14 | 🔴 Стартует собеседование в прямом эфире
Проводи Михаила Горюнова @Harmonizr, разработчик Android-приложений, библиотек и инструментов.
Миша будет собеседовать на позицию Android разработчика без уровня (требования здесь)
P.S. Запись останется на канале
#AndroidBroadcast #собеседование | 14 |
| 15 | Парсинг ботокоманд
/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 |
