Тоже максимально непонятен энтузиазм по поводу Island, Insular и других подобных "решений" на Android. Рабочий профиль не помогает даже от такой примитивной проверки буквально в несколько строк кода
Спасибо большое за отличный инструмент. MacOS Sequoia, автоподбор сработал для ютуба, для дискорда пришлось вручную тестить стратегии одну за другой, пока не нашлась рабочая. ВПН - это хорошо, но еще лучше - всегда иметь под рукой инструмент локального обхода блокировок и цензуры. И чем более развитыми и верхнеуровневыми будут эти тулзы, тем лучше. Портировать бы еще на Linux, Android и iOS - и вообще красота. Но понятно, что на это нужно значительно больше ресурсов и усилий... Все равно спасибо за прорывной для коммьюнити проект
Да, это так. Вероятно, ещё и потому, что телеграм старше компоуза лет на 5-7. Весь исходный код тг доступен публично на гитхабе, есть его видео-разборы.
Интересно, что там так же сделано, через запись экрана. Библиотека в данном случае имеет преимущество гибкой настройки, можно обернуть и в анимацию как у jb, и в любую другую с небольшим количеством изменений
Спасибо! Конечно, реализация в телеги отличается в нюансах) С учетом того, что там нет компоуза и нет даже котлина, все на чистой джаве. Но в общих чертах алгоритм такой же, да.
В целом термины reference equality (сравнение по ссылке), instance equality (сравнение по экземпляру/инстансу) и "сравнение по адресу в памяти" используются в статье синонимично, потому что reference equality это по определению проверка, что две ссылки в стеке указывают на один и тот же адрес в куче (формулировка грубая, но вроде не грешащая против основ JMM).
И да, вы совершенно правы, это дефолтная реализация equals.
По поводу делегата - точнее будет сказать, что для переменных с делегатом ключом в remember добавляется делегат, а не значение. В байткоде это тоже видно
Третья строка снизу: композер проверяет изменение делегата. В этом случае пересоздавать лямбду не имеет смысла, потому что делегат при обращении всегда предоставит актуальное значение. Аналогично, кстати, работает derivedStateOf, добавлять ключ в remember не нужно:
var imagesCount by remember { mutableStateOf(10) }
val isEmpty by remember { derivedStateOf { imagesCount == 0 } }
По поводу адреса в памяти - выразился так для простоты, в соответствии с гайдом гугла по strong skipping: "Unstable parameters are compared using instance equality (===)" (https://developer.android.com/develop/ui/compose/performance/stability/strongskipping). За что купил, за то и продаю) Насчет equals действительно хорошее наблюдение, проверка по инстансу в памяти это дефолтная реализация equals, очевидно имеется в виду она. При этом если переопределить equals на вечный true, проверка по инстансу не сработает. Гугловая дока врет.
Конечно, по сути сеньорность определяется просто: если ты выходишь на рынок и рандомный ТЛ готов предложить за твою экспертизу (софт и/или хард) овер 300К - то не важно, сколько тебе лет.
В абстрактных рассуждениях на эту тему очень мало смысла, все зависит от конкретики.
Каждый 22-23-летний senior специалист (включая меня), читая ваш комментарий, нервно сглотнул) Интересно, может ли причинно-следственная связь работать в обратную сторону: не "молодых сеньоров мало, так как они неопытны", а "молодых сеньоров мало, так как их опыт никто не воспринимает всерьез лишь потому, что они молоды". Иначе говоря, можно ли "загасить" амбиции молодого и рвущегося в бой разраба подходом "всякий сверчок знай свой шесток"? Возможно, меня закидают тухлыми помидорами, лишь хотел поделиться мыслями вслух
Билдер корутин launch берет из скоупа, от которого вы запускаетесь, контекст, включая пуллы потоков, джобы, хендлеры ошибок и все прочее. Зачем тут дублирование?
Кроме того, флоу в объекте Downloader мутабельны и публичны, что дает возможность эмитить в них из любого места во всей кодовой базе.
val sizeFlow = MutableSharedFlow<Progress>()
Хорошая практика - оставлять мутабельную версию флоу приватной, а наружу выставлять только иммутабельный флоу:
private val _sizeFlow = MutableSharedFlow<Progress>()
val sizeFlow = _sizeFlow.asSharedFlow()
Забавно, вы как будто вообще не поняли, о чем статья) Речь идёт о загрузке данных с сервера, загрузке именно по сети. Вы будете использовать для этого parametersOf? Хотел бы на это посмотреть)
Далее, если вы используете KMP, лучше не выставлять наружу suspend методы вьюмодели, иначе в Свифте придется оборачивать в try await или работать с коллбэками. Синхронный метод для бо́льшего удобства.
Далее, если вы используете загрузку данных с сервера, можно, конечно, их закешировать в локальную БД, но тогда придется решать вопрос, когда инвалидировать этот кэш, как синхронизировать его с удаленным источником данных и так далее. Кроме того, если вы используете оптимистические апдейты, а сервер за вами "не поспевает" или запрос упал с ошибкой - опять же, возникнет рассинхрон с сервером.
Поэтому на практике часто "списочный" экран напрямую обновляется свежими данными с серва.
Изначально Котлин так и задумывался, но сейчас это уже давно не так. Во-первых, существует Kotlin Native. Это технология, которая позволяет кастомным компилятором собирать исходники на Kotlin в нативные бинарники. Благодаря ей можно писать приложения для iOS, например. Можно конечно писать и для винды или линукса, как на C, но это не очень популярный способ)
Есть ещё Kotlin JS, транспилятор, который преобразует код на котлине в код на JS, и Kotlin WASM, который может исполнять код на котлине в браузере при помощи WebAssembly.
К сожалению, тут хочется поправить скорее автора статьи
И от авторов Свифта тогда тоже. Из официальной документации Swift:
Swift uses variables to store and refer to values by an identifying name. Swift also makes extensive use of variables whose values can't be changed. - "Свифт использует переменные, чтобы сохранять и ссылаться на значения по имени. Свифт также активно использует переменные, значения которых не могут быть изменены."
Может быть, если весь мир не прав, а вы правы, стоит задуматься?
Печально каждый раз видеть, как люди путают Kotlin Multiplatform, который уже давно Stable, и Compose Multiplatform, который Stable для Android и Desktop, Beta для iOS и Alpha для Web. В этой статье вообще про Compose Multiplatform пара предложений (видимо, автор оригинального материала не вполне в курсе последних апдейтов и релизов), а между тем фреймворк уже сейчас вполне может соперничать с Flutter. По пути своего развития он будет собирать все те же проблемы, что и Flutter: производительность, поддержка собственного канваса на iOS, баги платформенных реализаций под капотом, и т. д.
Но гибкость Compose Compiler и Compose в целом как инструмента реактивного декларативного UI рвет на части все. Будем дальше наблюдать за этой эпической битвой)
Полностью согласен с названием статьи, но содержание разочаровало. Гораздо полезнее для новичков было бы понять, почему лучше стартовать с языка со строгой типизацией и иммутабельностью, типа Go, Kotlin или Swift
Интересно, как обрабатывать состояния таких View Model в Swift UI. Если я правильно понимаю, интерфейс от них реактивно обновляться не будет? Было бы здорово, если бы Google выпустили официальный аналог https://github.com/rickclephas/KMM-ViewModel или предложили свое решение, если ksp-генерация это некрасиво.
Тоже максимально непонятен энтузиазм по поводу Island, Insular и других подобных "решений" на Android. Рабочий профиль не помогает даже от такой примитивной проверки буквально в несколько строк кода
Единственный надежный вариант - полноценно рутовать девайс
Есть ByeDPIAndroid
https://github.com/dovecoteescapee/ByeDPIAndroid
Если поиграться с настройками, оживает даже инстаграм
Спасибо большое за отличный инструмент. MacOS Sequoia, автоподбор сработал для ютуба, для дискорда пришлось вручную тестить стратегии одну за другой, пока не нашлась рабочая.
ВПН - это хорошо, но еще лучше - всегда иметь под рукой инструмент локального обхода блокировок и цензуры. И чем более развитыми и верхнеуровневыми будут эти тулзы, тем лучше.
Портировать бы еще на Linux, Android и iOS - и вообще красота. Но понятно, что на это нужно значительно больше ресурсов и усилий... Все равно спасибо за прорывной для коммьюнити проект
В последних версиях compose, если вы не выключаете strong skipping, да, можно забить.
Да, это так. Вероятно, ещё и потому, что телеграм старше компоуза лет на 5-7. Весь исходный код тг доступен публично на гитхабе, есть его видео-разборы.
Не видел, теперь видел, спасибо)
Интересно, что там так же сделано, через запись экрана. Библиотека в данном случае имеет преимущество гибкой настройки, можно обернуть и в анимацию как у jb, и в любую другую с небольшим количеством изменений
Спасибо! Конечно, реализация в телеги отличается в нюансах) С учетом того, что там нет компоуза и нет даже котлина, все на чистой джаве. Но в общих чертах алгоритм такой же, да.
Не хочу сильно душнить, но использование composed модификатора больше не рекомендуется использовать - в пользу Composable фабрик.
В целом термины reference equality (сравнение по ссылке), instance equality (сравнение по экземпляру/инстансу) и "сравнение по адресу в памяти" используются в статье синонимично, потому что reference equality это по определению проверка, что две ссылки в стеке указывают на один и тот же адрес в куче (формулировка грубая, но вроде не грешащая против основ JMM).
И да, вы совершенно правы, это дефолтная реализация equals.
По поводу делегата - точнее будет сказать, что для переменных с делегатом ключом в remember добавляется делегат, а не значение. В байткоде это тоже видно
Третья строка снизу: композер проверяет изменение делегата. В этом случае пересоздавать лямбду не имеет смысла, потому что делегат при обращении всегда предоставит актуальное значение.
Аналогично, кстати, работает derivedStateOf, добавлять ключ в remember не нужно:
По поводу адреса в памяти - выразился так для простоты, в соответствии с гайдом гугла по strong skipping: "Unstable parameters are compared using instance equality (===)" (https://developer.android.com/develop/ui/compose/performance/stability/strongskipping). За что купил, за то и продаю)
Насчет equals действительно хорошее наблюдение, проверка по инстансу в памяти это дефолтная реализация equals, очевидно имеется в виду она. При этом если переопределить equals на вечный true, проверка по инстансу не сработает. Гугловая дока врет.
Всегда пожалуйста)
Конечно, по сути сеньорность определяется просто: если ты выходишь на рынок и рандомный ТЛ готов предложить за твою экспертизу (софт и/или хард) овер 300К - то не важно, сколько тебе лет.
В абстрактных рассуждениях на эту тему очень мало смысла, все зависит от конкретики.
Каждый 22-23-летний senior специалист (включая меня), читая ваш комментарий, нервно сглотнул)
Интересно, может ли причинно-следственная связь работать в обратную сторону: не "молодых сеньоров мало, так как они неопытны", а "молодых сеньоров мало, так как их опыт никто не воспринимает всерьез лишь потому, что они молоды". Иначе говоря, можно ли "загасить" амбиции молодого и рвущегося в бой разраба подходом "всякий сверчок знай свой шесток"?
Возможно, меня закидают тухлыми помидорами, лишь хотел поделиться мыслями вслух
Интересный код однако)
Билдер корутин launch берет из скоупа, от которого вы запускаетесь, контекст, включая пуллы потоков, джобы, хендлеры ошибок и все прочее. Зачем тут дублирование?
Кроме того, флоу в объекте Downloader мутабельны и публичны, что дает возможность эмитить в них из любого места во всей кодовой базе.
Хорошая практика - оставлять мутабельную версию флоу приватной, а наружу выставлять только иммутабельный флоу:
Забавно, вы как будто вообще не поняли, о чем статья) Речь идёт о загрузке данных с сервера, загрузке именно по сети. Вы будете использовать для этого parametersOf? Хотел бы на это посмотреть)
Далее, если вы используете KMP, лучше не выставлять наружу suspend методы вьюмодели, иначе в Свифте придется оборачивать в try await или работать с коллбэками. Синхронный метод для бо́льшего удобства.
Далее, если вы используете загрузку данных с сервера, можно, конечно, их закешировать в локальную БД, но тогда придется решать вопрос, когда инвалидировать этот кэш, как синхронизировать его с удаленным источником данных и так далее. Кроме того, если вы используете оптимистические апдейты, а сервер за вами "не поспевает" или запрос упал с ошибкой - опять же, возникнет рассинхрон с сервером.
Поэтому на практике часто "списочный" экран напрямую обновляется свежими данными с серва.
Изначально Котлин так и задумывался, но сейчас это уже давно не так. Во-первых, существует Kotlin Native. Это технология, которая позволяет кастомным компилятором собирать исходники на Kotlin в нативные бинарники. Благодаря ей можно писать приложения для iOS, например. Можно конечно писать и для винды или линукса, как на C, но это не очень популярный способ)
Есть ещё Kotlin JS, транспилятор, который преобразует код на котлине в код на JS, и Kotlin WASM, который может исполнять код на котлине в браузере при помощи WebAssembly.
К сожалению, тут хочется поправить скорее автора статьи
И от авторов Свифта тогда тоже. Из официальной документации Swift:
Swift uses variables to store and refer to values by an identifying name. Swift also makes extensive use of variables whose values can't be changed. - "Свифт использует переменные, чтобы сохранять и ссылаться на значения по имени. Свифт также активно использует переменные, значения которых не могут быть изменены."
Может быть, если весь мир не прав, а вы правы, стоит задуматься?
Печально каждый раз видеть, как люди путают Kotlin Multiplatform, который уже давно Stable, и Compose Multiplatform, который Stable для Android и Desktop, Beta для iOS и Alpha для Web. В этой статье вообще про Compose Multiplatform пара предложений (видимо, автор оригинального материала не вполне в курсе последних апдейтов и релизов), а между тем фреймворк уже сейчас вполне может соперничать с Flutter. По пути своего развития он будет собирать все те же проблемы, что и Flutter: производительность, поддержка собственного канваса на iOS, баги платформенных реализаций под капотом, и т. д.
Но гибкость Compose Compiler и Compose в целом как инструмента реактивного декларативного UI рвет на части все. Будем дальше наблюдать за этой эпической битвой)
Полностью согласен с названием статьи, но содержание разочаровало. Гораздо полезнее для новичков было бы понять, почему лучше стартовать с языка со строгой типизацией и иммутабельностью, типа Go, Kotlin или Swift
Интересно, как обрабатывать состояния таких View Model в Swift UI. Если я правильно понимаю, интерфейс от них реактивно обновляться не будет? Было бы здорово, если бы Google выпустили официальный аналог https://github.com/rickclephas/KMM-ViewModel или предложили свое решение, если ksp-генерация это некрасиво.