Ракету пустил и забыл. Или как заставить DI работать

от автора

Ваш первый день на работе. Вчера вы рассказывали про чистую архитектуру, SOLID принципы, и про то, как создавать аккуратную и масштабируемую архитектуру.

Сегодня нужно написать простенький экран, который будет отображать список. Вы с огромным энтузиазмом начинаете реализовывать прекрасный список — каталог товаров магазина. Один запрос, один список. Все сделали красиво, фрагмент создался, подтянул из

Hidden text

Однажды как-то студент к нам пришел с огромным потенциалом, но может быть с маленьким опытом, от студента мы многого и не ждали. Надеюсь, после встречи со мной, он не передумал пробовать мобилки и еще когда-нибудь придет к нам на собеседование.

Общаясь с ребятами, как-то неожиданно я для себя понял, что никто почти не задумается о смысле одного из основополагающих инструментов в class ShowCaseViewModel : ViewModel { fun loadCatalog(){ scope.launch { // long request with caching. // request prices // Collect data from few interactors // merge lists // filter list // sort list } } }

Теперь, сохранив эту ViewModel как WeakRefence мы получем, что при открытии экрана загрузка продолжается как ни в чем не бывало. Корутина удерживается, так лежит в очереди, и последовательно вызывается на треде. Тело корутины в своем случае удерживает сам ViewModel. Все это можно будет переиспользовать при возвращении на экран. По завершении загрузки, если пользователь не будет долго заходить на экран, все будет уничтожено, память освобождена.

Stone, как система

Выбор положен, ты решил писать свою библиотеку DI. И даже определил принципы для нее. Прежде всего она не должна держать чужие компоненты. Очевидно, что жизненный цикл компонентов приложения определяется их держателями и теми, кто их использует. Так к примеру Activity удерживается Андройдом, View удерживается Activity, ViewModel удерживается вьшкой, и так до самого DataSource.

Hidden text

Если быть детальнее, то Activity удерживается в ActivityThread и в ApplicationThread.

DI свои скоупы не нужны, все эти скоупы определяются логикой приложения. DI же выполняет простую задачу — сгенерировать новый компонент, либо предоставить, то, что уже сгенерирован.

Твое желание, похвально, но что если, я скажу, что решение уже есть. И я готов тебе дать, за просто так. И оно выглядит так.

class ShowCaseFragment : Fragment() {      @Inject     lateinit var viewModel: ShowCaseViewModel       override fun onCreate(savedInstanceState: Bundle?) {         super.onCreate(savedInstanceState)         DI.inject(this)     }  }

Неожиданно, правда. Не часто видишь, что ViewModel предоставляется без ViewProvider. Да, именно так все и должно быть. Нам не нужны больше дополнительные фабрики, провайдеры, менеджеры компонентов. Все потому, что DI это все предоставляет.

@Component interface AppComponent {      fun viewModelsModule(): ViewModelsModule      fun inject(showCaseFragment: ShowCaseFragment)  }  @Module interface ViewModelsModule {      @Provide(cache = Provide.CacheType.Weak)     fun provideShowCaseViewModel(): ShowCaseViewModel {         return ShowCaseViewModel()     }  }

Приложение это использует. И если приложение использует свои компоненты, то Weak ссылка не обнулится, а значит твой компонент не потеряется. DI обязательно предоставит его еще раз для экрана, если одно не было уничтожено сборщиком мусора.

Сложности применения

Рассказ получается прекрасным, даже немного поэтичным. Но все ли так хорошо, как хорошо на бумаге. Конечно же нет, в отличие от дядюшки Боба стоит также говорить о реальных вещах, где может сломать, что нужно учесть. Пройдемся по очевидным проблемам, и что с ними делать.

Первая, и самая важная — потеря состояния. Сразу переехать на новую идею не получится, даже наскоком с надеждой, что все протестируется — нет. Раньше все, что вы делали в компоненте, будем говорить о ViewModel, чудесным образом исчезнет с новым открытием экрана. Вы могли оставить там все что хотели, сейчас нет. Та же ViewModel вам может вернуться заново, и все что вы там повыставляли в переменных, все может сохраниться (а может и нет). Так что будте бдительны, теперь вам надо самостоятельно управлять Stone. Оставляй лайки и комментарии, и я продолжу рассказывать про DI, в работе.


ссылка на оригинал статьи https://habr.com/ru/articles/754580/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *