Артур Артиков @a_artikov
Тимлид, Android-разработчик
Information
- Rating
- Does not participate
- Location
- Санкт-Петербург, Санкт-Петербург и область, Россия
- Date of birth
- Registered
- Activity
Specialization
Mobile Application Developer
Lead
Android development
Спасибо за статью.
Можете, пожалуйста, раскрыть этот момент? Злоумышленник сможет сделать это, не имея доступа к нашему беку?
Привет. Крутая статья.
А как модификация байткода влияет на время сборки проекта?
Подписку на ChatGPT Plus можно получить и из России. Для этого нужны: впн, сервис для подтверждения смс (например, sms activate), виртуальная карта зарубежного банка (например, сервис pyypl).
Цена - 20$ в месяц. Но за то есть все функции: GPT 4 с ограничением 50 запросов в 3 часа, Advanced Data Analysis, генерация изображений через Dalle 3, распознавание содержимого на изображениях, поиск информации в интернете, сотни дополнительных плагинов.
Крутая статья. Очень жду продолжения)
Классная статья.
Подскажите, Кандинский поддерживает inpainting? Эта фича есть в Stable Diffusion. С ее помощью можно выделить часть изображения и сгенерировать заново. Очень полезно, чтоб исправлять проблемы с лицом, руками, оружием и т. д.
Inpainting полностью меняет рабочий процесс. С ним мы не пытаемся получить шедевр одним запросом, а итеративно приближаемся к нему.
В отличие от
StateFlow
уFlow
нельзя получить текущее значение. Это значит, что вcollectAsState
мы будем обязаны передать аргументinitial
- в этом неудобство.Про
derivedStateOf
просто проверьте, если не верите.combine
возвращаетFlow
. Утилитаderived
будет возвращатьStateFlow
, чтоб было удобнее.Про
derivedStateOf
вы ошибаетесь. Она неявно подписывается на поля из лямбда-функции и потом автоматически пересчитывается при изменении любого из них.Спасибо за дополнение.
Я не пробовал использовать упомянутые вами паттерны для реализации компонентного подхода. Будет интересно попробовать.
Выносить логику в UI, конечно, не стоит.
А вот второй вариант - создать еще одно поле, которое будет автоматически вычисляться на основе других полей, по-моему, хороший. Вопрос в том, как это сделать удобнее.
Если вы используете
StateFlow
, то нужно написать утилитную функцию (назовем ееderived
) для комбинирования flow. С ней код получится таким:Или можно для состояния компонентов использовать
State
из Jetpack Compose и встроенную функциюderivedStateOf
. Получится так:Расскажите, пожалуйста, с какими неудобствами вы столкнулись, используя MVVM с Jetpack Compose?
Привет, Саша.
Я сделал
login
,password
иinProgress
отдельными полями, потому что они могут изменяться независимо друг от друга. Если делать состояние компонента единым объектом, то это уже будет ближе к MVI, нежели к MVVM. Я не фанат MVI и редко его использую. Но, если тебе нравится MVI, то, конечно, его можно применять с компонентным подходом.В реальных приложениях я использую DI-фреймворк Koin. Для этого я создаю класс
ComponentFactory
— обертку поверх DI-контейнера с методами для создания компонентов. СамComponentFactory
тоже зарегистрирован в DI, поэтому компоненты могут получить к нему доступ. Вот gist с примером.Спасибо за интересные вопросы.
Вы спрашиваете про реализацию компонентного подхода. Этому будет посвящена моя следующая статья, которая выйдет через пару дней.
Я не использую фрагменты и библиотеку ViewModel, поэтому не хотел бы выдумывать, как их лучше всего применить. Давайте, я попробую дать универсальные рекомендации по вашим вопросам.
Про получение данных в компонентах
По возможности я стараюсь делать компоненты независимыми друг от друга. Для задачи "загрузить данные с сервера и отобразить их на экране" это всегда получается сделать.
Предположим, что есть
Компонент А
и ему нужны какие-то данные с сервера. И естьКомпонент Б
, которому нужны те же самые данные.Можно сделать, чтоб
Компонент А
грузил данные, аКомпонент Б
как-то вытаскивал их изКомпонента А
. Но это плохое решение. Оно создает лишние зависимости между компонентами.Я предлагаю поступить по-другому. Пусть оба компонента обращаются за данными в репозиторий. Репозиторий нужно сделать достаточно умным — он должен выполнять дедупликацию запросов. Это значит, что если к нему обратиться за одними и теми же данными в течение небольшого промежутка времени, то сетевой запрос выполнится всего один раз.
Итого, компоненты, которые просто грузят и отображают данные, можно сделать независимыми.
Конечно, бывают более сложные случаи, когда компоненты взаимодействуют друг с другом. В следующей статье я расскажу про это подробнее.
Про ЖЦ функциональных блоков
Если один и тот же функциональный блок нужен на нескольких экранах, то я просто создаю на нужных экранах по инстансу этого функционального блока. Как правило, время жизни функционального блока совпадает с временем жизни экрана. Но, наверное, бывают случаи, когда функциональные блоки появляются и пропадают динамически, тогда время жизни не будет совпадать.
Нет, это значит, что компонентный подход был применен неправильно. Вы ударили себе молотком по пальцу и из этого сделали вывод "Молотки - это плохо".
Не надо так делать, и тогда будет счастье)
Суть компонентного подхода - разделить сложную штуку на более простые части. Это не может не работать.
А вот криво реализовать это в коде, конечно, можно. Тут с вами спорить не буду)
Я имел ввиду, почему не делать, чтоб функция возвращала данные в случае успеха и кидала исключение при ошибке?
А почему бы не использовать исключения для ошибок?
Но эти имена не надо напрямую использовать в лайаутах и стилях. Надо завести в теме атрибуты, имеющие уже семантические имена и ссылающиеся на цвета, и использовать их.
Меня это тоже расстроило. Но потом оказалось, что в material-component поддерживается
lineHeight
(ссылка на код).Вопрос не по теме. В вашей компании есть опыт использования скриншотов для автоматизации тестирования?
В разделе "Проблема" ставится задача "Отобразить ленту с двумя типами данных — текст с описанием и картинка", а в разделе "Решение" решается другая задача.