Artyom
Нужно же выпилить и повозможности не сломать то, что сделано
Кирилл
Single — это тот самый мутабельный синглтон, который повышает степень связности до 146%?
Не. Это просто объект, который создаётся один раз в памяти и висит там вместе с приложением. Это объект класса, которому ты можешь передать зависимости, а потом он будет там висеть. Например: бд объект. Прокидываешь ему нужные арги и он висит всё время, в нужные классы, которые будут использовать бд, ты инжектишь этот объект.
Mike
Звучит как синглтон/статик.
Vladislav
Здравствуйте! Не могу вызвать метод show для DialogFragment. Использую такую цепочку public abstract class AbstractDialog <P extends AbstractDialogPresenter> extends DialogFragment implements LifecycleOwner public class DialogCategory extends AbstractDialog<CategoryPresenter> implements ICategoryView DialogFragment dialog = new DialogCategory(); dialog.show(getFragmentManager(), Constants.DIALOG_CATEGORY);
Кирилл
Звучит как синглтон/статик.
Ну почти. Это объект, которому ты даёшь необходимые данные перед тем, как начать работу. А уже потом он висит в памяти.
Кирилл
Если не нравятся синглы - можно скоупы, кто против.)
Vladislav
Каким образом?)
Vitaliy
Все модно стильно молодежно а потом в самсунгах на некоторых устройствах в случайную лунную ночь при старте сервиса берется не кастомый Application, а дефолтный типа сюрприз
Vladislav
Под клин переписываю, даггер внедряю
Кирилл
Звучит как синглтон/статик.
Выглядит это как-то так: class Foo(val bar: Bar) val fooModule = module { single { Foo(get()) } } А потом в onCreate аппликейшена startKoin(this, listOf(fooModule, ...))
Кирилл
Особенно удобно это когда у тебя всё на контрактах висит. Тогда это наиболее удобно - ты инъектишь определенные объекты, но не заботишься что это за объекты.
Павел 🍵
GCM_HB_ALARM release without a matched acquire(ошбка wakelock) сейчас получил ошибку, когда аларм должен был сработать но нет, где можно почитать как работает, у меня для приложения выключен режим экномии батареи
Кирилл
Что делает startKoin и как потом забирать зависимости?
startKoin грузит модули и привязывает их к жц приложения. А инъектить можно двумя способами val foo: Foo = get() Или val foo: Foo by inject() // lazy
Mike
startKoin грузит модули и привязывает их к жц приложения. А инъектить можно двумя способами val foo: Foo = get() Или val foo: Foo by inject() // lazy
Ясно. Клуб любителей сильного связывания, процедурного программирования и однократного использования кода. Спасибо.
Mike
*слабого
Отнюдь. На один интерфейс — одна реализация, следовательно, завязка на реализацию (и нарушение DIP).
Кирилл
Отнюдь. На один интерфейс — одна реализация, следовательно, завязка на реализацию (и нарушение DIP).
А я тебе о чём? Ты можешь делать интерфейс и потом инъектить нужную реализацию. Не заботясь о том, что это за реализация. Ну, если у тебя конечно действительно лишь одна реализация.
Mike
Ну вот. С несколькими реализациями это не работает -> сильное связывание.
Кирилл
Типа interface Foo class FooImpl(val bar: Bar) : Foo И потом после загрузки и всего этого val foo: Foo by inject()
Кирилл
Ну вот. С несколькими реализациями это не работает -> сильное связывание.
А прокидывание зависимостей руками - это прям не сильное связывание?
Mike
А прокидывание зависимостей руками - это прям не сильное связывание?
Нет, потому что в разные экземпляры одного класса можно по ситуации закинуть разные зависимости. Собственно, это и есть повторное использование кода и слабое связывание.
Кирилл
Нет, потому что в разные экземпляры одного класса можно по ситуации закинуть разные зависимости. Собственно, это и есть повторное использование кода и слабое связывание.
Это мы сейчас про синглы говорили. В скоупах ты можешь прокидывать что захочешь, куда захочешь и сам управляешь жц. Ну, конечно его ещё можно тоже подписать на жц аппликейшена. Но удалять и пересоздать можешь руками.
Кирилл
Выглядит как ручное прокидывание зависимостей.
Давай на примерах, а то я перестаю улавливать нить твоей логики. Например: залогиненный юзер, у которого есть имя и фамилия. Потом тебе этот пользователь понадобится в разных местах по всему приложению. Твои действия (без койна)?
Кирилл
Т.е. когда разлогинился - нужно выгрузить его. А потом при новом логине загрузить снова.
Alexey
В jsr330 есть аннотация named для этого
Mike
а, ну и при создании экранов буду в них совать этого юзера, активити при этом будет выступать DI-контейнером / god object'ом.
Кирилл
Сохраню в префы с именем currentUser
Как это делается в коине: объявляешь скоуп с юзером, которому нужны name и surname как зависимости. Потом отдаешь эти данные коину. Когда создаёшь скоуп - коин находит эти данные и суёт их в юзера. Потом, в любой момент в приложении ты получаешь юзера через обычный инъект. И ты не заботишься ни о чём. Главное - выгрузить скоуп когда юзер разлогинился. Таким образом ты не заботишься, откуда придёт этот объект класса User, когда он создаётся и когда умирает - это всё в отдельных классах. Ты просто инъектишь и используешь. И почему это удобно вместе с клином: я не инъектю зависимости в активити/фрагмент. Иногда мне зависимость нужна в презентере или репозитории. Я не забочусь об их передаче из активити/фрагмента и т.д. Я просто использую.
Mike
Всё круто, когда в одном скоупе на один интерфейс — одна реализация. А если попытаться использовать интерфейсы по назначению, наделать горы реализаций и попытаться повторно использовать код — получится облом.
Кирилл
Всё круто, когда в одном скоупе на один интерфейс — одна реализация. А если попытаться использовать интерфейсы по назначению, наделать горы реализаций и попытаться повторно использовать код — получится облом.
Если у тебя несколько скоупов или синглов, в которых хранятсч объекты одного и того же типа - делаешь const val с именем этой зависимости. Например: const val fooName1 = "foo name 1" const val fooName2 = "foo name 2" scope(fooName1) { Foo(get("bar1") } scope(fooName2) { Foo(get("bar2") } Если осмысленно назвать - можно так же улучшить читабельность кода за счёт разделения объектов по смыслу. И не обязательно инъектить в готовый объект же. При создании инстанса ты можешь передать в конструктор просто get() или get(fooNameN). И не нужно будет привязывать к определенной реализации. Зато получение нужных объектов очень простое.
Кирилл
А какая мне разница — передавать/прокидывать имя или сразу реализацию?
Как минимум: ты становишься независимым от места получения нужной зависимости. Не хранишь её в определённом месте, а просишь позаботиться об этом koin-a.
Mike
Как минимум: ты становишься независимым от места получения нужной зависимости. Не хранишь её в определённом месте, а просишь позаботиться об этом koin-a.
Станосишься зависимым от правильного написания имени зависимости. Плодишь для этого константы. Привет, динамические языки.
Кирилл
И как минимум - коин избавляет от котлиновского object-a без конструктора. Просто юзаешь single.
Кирилл
Станосишься зависимым от правильного написания имени зависимости. Плодишь для этого константы. Привет, динамические языки.
Я могу так же сказать: ты становишься зависимым от места получения и правильного прописывания названия переменной. Ну кек же.
Кирилл
И имя зависимости при условии нескольких реализаций одного интерфейса.
Кирилл
В ином случае это не нужно.
Mike
В ином случае это не нужно.
Иной случай не нужен.
Кирилл
Нет, система типов не позволит опечататься.
Ок, делаешь companion object, в котором и хранить эти const val метки, а ещё делаешь простой метод get(label: String): Foo, который в зависимости от лейбла выдаёт тебе ту или иную реализацию этого класса. Метод 1 строчкой (для красоты можно 2), сам компаньон и лейблы - ещё несколько строчек. И напоминаю: это только для интерфейсов с несколькими реализациями. Зато твой код становится независимым от места получения. Из аппликейшена, из коина, из преферанса - да по-барабану. И не нужно получать эту зависимость в активити/фрагменте, а потом передавать куда-то дальше.
Mike
Усложняем задачу: нужно заинжектить реализацию интерфейса, у которой тоже есть зависимости...
Кирилл
Усложняем задачу: нужно заинжектить реализацию интерфейса, у которой тоже есть зависимости...
Так в начале же было. Передаешь эту зависимость койну, потом когда креейтишь скоуп, то он сам находит и передаёт эту зависимость в конструктор.
Корбен
Ребят кто в курсе сколько стоит час андроид разработки?
Кирилл
Ребят кто в курсе сколько стоит час андроид разработки?
По-разному, в зависимости от твоего опыта.
Сергій
бери 50 баксов, не ошибёшься )
Сергій
если скилл позволяет
Mike
Так в начале же было. Передаешь эту зависимость койну, потом когда креейтишь скоуп, то он сам находит и передаёт эту зависимость в конструктор.
Тривиалиная задача с разными реализациями уже решается непросто. А если реализациям тоже нужно передавать разные реализации, можно сразу вешаться. Это как дженерики в дженериках.
Корбен
По-разному, в зависимости от твоего опыта.
А если по категориям то какая сколько?)
Сергій
Жирно
где как, парень никакой инфы не дал, может он про США спросил )
Кирилл
Тривиалиная задача с разными реализациями уже решается непросто. А если реализациям тоже нужно передавать разные реализации, можно сразу вешаться. Это как дженерики в дженериках.
Так а кто заставляет везде обязательно использовать один инструмент? Много задач, когда коин помогает упростить разработку, при этом не доставляя боли.) Ну вот поэтому его и любят.)
Mike
Ну по категориям Джун Мидл Сеньор
И что эти категории значат?
Корбен
И что эти категории значат?
Ну типо джун начинающий Мидл-дрочер жуткий Сеньор-он вообще живёт за компом)
Кирилл
Было бы ещё круто, чтобы он какие-нибудь проблемы решал...
Ну он делает всё то, для чего придумали DI.
Корбен
О пасибо)
Unat
Ну типо джун начинающий Мидл-дрочер жуткий Сеньор-он вообще живёт за компом)
неправильно узнавать сколько просит за час сеньор и сколько просит джун. Сеньор не станет пилить лэндинг, джун не осилит сложное приложение. Нужно от задачи отталкиваться.
Olexandr
как записать текущий аудио поток в файл? MediaRecorder не предлагать, он пишет с микрофона )
Olexandr
не знаю)
Olexandr
?
Сергій
погугли
Семен
Стоит ли создавать класс AsyncTask в другом файле? Или лучше в одном классе с Activity
Sergey
Ну мне чет кажется это плохой идеей. Я бы старался в Активити оставлять только то, что отвечает за визуальное отображение. Можно интерфейс из активити передать в модель, где этот АсинкТаск реализуется.
Sergey
Ну так ему ж надо чето обновить в Активити при onComplete() или как там метод называется
Семен
получается нужно получить колбек в onPostExecute
Olexandr
погугли
не поддерживает exo player такую функцию
ᛖᚹᛋᛁᚱ
получается нужно получить колбек в onPostExecute
Или отдавай активити в билдере асинктаску через WeakReference
roman G
Есть приложение, которое делает фото, и сохраняет его в галерею Нужно сделать вывод всех фото, которые были сделаны в моём приложении. Есть две идеи: 1 - хранить пути к фото в БД и если потом фото не будет найдено, то мы удаляем его путь из БД 2 - хранить во внутренней памяти, но тогда я не буду знать, было-ли удалено фото из галереи
ᛖᚹᛋᛁᚱ
И реализовать обновление уи функцию
Семен
Или отдавай активити в билдере асинктаску через WeakReference
я хотел так. Но студия пишет что будет мемори лик
Семен
у контекста
ᛖᚹᛋᛁᚱ
Да