есть логика, которая должна быть на всех используемых фрагментах, вот думаю, что если я создам абстрактный класс фрагмента, в который буду инжектить commonViewModel? Т.е. в реализации фрагмента своя вьюмодель, а у абстрактного родителя своя.
Не сойдёт ли с ума инжектор зависимостей?
Мб как вариант использовать вм активити
Увы, нужна именно привязка к конкретным фрагментам чтобы юзать правильный fragmentManager. В общем инжектор действительно сходит с ума, т.к. сразу видит 2 модели которые надо заинжектить, но умеет инжектить только одну. Тут как я понял два варианта: 1. Инжектить обе вьюмодели в реализации фрагмента (Но тогда в каждой реализации надо не забывать об этом) 2. Вместо инжекта тянуть конкретный инстанс, что я и сделал. И вроде бы это то, что надо Реализация спокойно инжектит поля помеченные inject, а абстрактный класс ручками тянет нужный ему инстанс и они не мешают друг другу
Можно иметь shared viewmodel, привязанную к активити. Другой вопрос, нужно ли)
у тебя вьюмодель инжектится прямо в поле фрагмента? @Inject val viewModel = .... вот так?
Увы, но не подходит, у меня у каждого фрагмента должна быть своё личное состояние, т.е. каждому нужна своя вью модель, но такая же как у всех. Мой вариант в целом рабочий, я только пытаюсь сейчас сделать так, чтобы вьюмодель стопила подписку, когда привязанный к ней фрагмент невидим пользователю, пока сделал это прокидывая во вьюмодель события onDesroyView и onCreateView
Слушай, а почему бы не сделать подкласс viewmodel с этой логикой? А потом наследуй VM фрагмента от этого класса, когда нужно
а что там за подписка такая, которую во вьюмоедли нужно стопить? Мб ее не нужно стопить? Мб она должна быть во фрагменте, а не во вьюмодели?
Думал об этом, на что-то странное выходит. Кейс такой: прилетают события - надо показать диалог. Т.е. на базовую VM, должен подписаться базовый фрагмент, а чтобы это сделать, нам в базовом фрагменте уже надо иметь ссылку на вьюмодель, получается надо её объявлять в базовом, а потом кастовать в наследнике к нужной... Попробую сделать так тестовый проект, а то чёт каша.
Во фрагменте сейчас и есть подписка, но нужно сохранять стейт полученный через неё, для этого используется deprecated retainInstance, от которого я пытаюсь избавиться.
а на чем реактивщина у тебя? лайвдата? флоу? Rx?
Не надо кастовать, иметь не надо тоже. Абстрактное поле для получения VM можно сделать в базе фрагмента. Возвращать будет не AbsVewModel, а дженерик
Repo -> VM - RX, VM -> View - LiveData
Попробую реализовать, спасибо
для сохранения стэйта в Rx есть BehaviorSubject
Увы не взлетело, споткнулся на том, что чтобы унаследоваться от VM, мне ей надо передать в конструктор нужные зависимости (репозиторий), а значит придётся его пихать во всех наследников
Тут можно схитрить - сделай инжект в поле)
а зачем Вам именно ViewModel?
Можешь сделать эту VM - компонентом коина. Грязноватый трюк, но в конструкторы не надо бросать ничего
У меня toothpick вместо коина. Но в итоге я походу сделал, получилась весёлая дичь с Warning'ами "Unchecked cast" и "Leaking 'this' in constructor of non-final class", но работает. Использовать это я конечно же не буду... https://gist.github.com/FirstSpectr/da22944e9300cbd003490818ff838e84
Можно базовый фрагмент сделать универсальнее, чтобы не делать кастов. BaseFragment<VM : BaseViewModelImpl> { abstract val viewModel: VM } Инжектить будешь конкретную реализацию вм в конкретной реализации фрагмента
Да, стало красивее, спасибо, обновил гист
Обсуждают сегодня