Comments 38
Serializable
использовать Pacrelable
, если Вы хотите более быстрой сериализации. К тому же, если Android SDK предоставляет возможность сохранять в Bundle сериализуемые объекты, то почему бы нам этим не воспользоваться, а не прикрываться фразами типа «медленная сериализация».Теперь по поводу «самописного DI». Если Вы внимательно читали статью, то я нигде не призывал отказываться от DI фреймворков, а наоборот предлагаю использовать подход, описанный в публикации, совместно c ними. Давайте возьмем для примера Dagger до появления функционала
AndroidInjection
, приходилось писать подобное (код с официального сайта):public class FrombulationActivity extends Activity {
@Inject Frombulator frombulator;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// DO THIS FIRST. Otherwise frombulator might be null!
((SomeApplicationBaseType) getContext().getApplicationContext())
.getApplicationComponent()
.newActivityComponentBuilder()
.activity(this)
.build()
.inject(this);
// ... now you can write the exciting code
}
}
Я лишь предлагал спрятать создание активити компонента. Примерно так.
interface Provider {
Builder getBuilder(FrombulationActivity activity);
}
class ProviderImpl implements Provider {
@Override
Builder getActivityComponent(FrombulationActivity activity) {
return ((SomeApplicationBaseType) getContext().getApplicationContext())
.getApplicationComponent()
.newActivityComponentBuilder()
.activity(activity)
.build();
}
}
public class FrombulationActivity extends Activity {
@Inject Frombulator frombulator;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// DO THIS FIRST. Otherwise frombulator might be null!
Provider provider = getIntent().getExtras().getSerializable(PROVIDER);
provider.getActivityComponent(this)
.inject(this);
// ... now you can write the exciting code
}
}
При таком подходе активити не знает откуда берется компонент. Если активити лежит в общей библиотеке, которую использую несколько приложений, то такой способ внедрения зависимостей очень удобен. А также при тестировании активити.
К тому же, хоть EventBus добавляет гибкости во взаимодействии между компонентами, он также накладывает больше ответственности на разработчиков — чтобы приложение не превратилось в запутанный клубок из событий. Лично я предпочитаю не злоупотреблять рассылкой событий и использовать EventBus только при острой необходимости.
Это худшее, что можно было посоветовать! Евентбас неявно связывает все компоненты между собой. Все компоненты в приложении могут слушать всех. А дебажить это дело…
Закопайте его и не вспоминайте
Я отлично представляю, где может понадобится рассылка сообщений компонентами. Но это не для общения между диалогом и активити. А именно в данном контексте я и не рекомендую слушать ваш совет.
Из-за использования инструментов в неправильных местах потом и получаются монстры, которых невозможно поддерживать и отлаживать.
Минус данного подхода, что вы отправляете сообщение в "комос", а кто его получит — неизвестно. Это влечет за собой проблемы отладки и связывает слушателей и источники событий. А кто эти источники и кто у них слушатели можно определить только глобальным поиском по проекту.
Это все равно что во всех интерфейсах передавать объекты типа Object и по мере их использования кастовать к нужным типам. А после этого заменить все интерфейсы на один:
interface Listener { fun doAction(obj: Object) }
Вы очень много пишите и уходите от темы в аналогии. Евентбас — зло для андроид приложений, так как он совершенно неконтролируем. Если проект маленький и его пилит один человек, который умудряется все держать в голове, то еще прокатит. Для серьезной разработки — это недопустимо.
Я думаю стоит завершить этот спор. Есди я вас не переубедил — это ваше дело. Но воздержитесь рекомендовать Евентбас кому-то еще.
habrahabr.ru/company/yamoney/blog/334500
habrahabr.ru/post/128772
Дабы не быть голословным, достаточно безобидный пример:
Есть LocalSocket. В доках ничего не сказано про параметр timeout в методе connect(). В исходниках сказано, что он игнорится. Угадаете, что происходит на самом деле?
Так что говнокодеры и тут и там :)
И как рассылка глобального сообщения по всему приложению связана с темой статьи — получения результата с диалога/соседнего фрагмента? Какая-то демагогия получается.
А по вашей теме — как я понимаю, вы хотите какой-то глобальный AlertDialog показывать в любом месте приложения при, скажем, получении какого-то сообщения из некого WebSocket-а. Не сказал бы, что эта идея мне нравится, но допустим, надо. Вы хотите куда-то EventBus-ом слать сообщения. Только непонятно, куда и кто должен на это реагировать. А вот как это сделать нормально (насколько слово «нормально» вообще применимо при подобной задаче. Берёте, регистрируете ActivityLifecycleEvents И при смене Activity, видимой для пользователя, запоминаете ее, а при необходимости берёте и показываете на ней, что хотите. Хотите — берёте ее контекст и Alertdialog/toast показываете, а может, вообще в decorview что-то вставляйте. А нет активных — пихаете сообщение куда-то в очередь или что у вас там. И никаких безликих event-ов в пустоту.
А каким боком EventBus к базе данных и серверу? :) И с чего вы взяли, что я не использовал EventBus? Пока что кроме пространных суждений я ничего не увидел. Медицинские системы зачем-то уже приплели. Мы тут вроде под Android пишем, судя по хабу.
По вашим словам поди и JavaScript (и любой не статически типизированный язык) лучше Java (любой статик), тем что в динамичном приложении нам не надо париться о конкретных типах, и мы можем на лету трактовать типы как удобнее. Ну-ну.
А про устойчивость и надежность вы думали? Статические анализаторы не просто так придумали.
Потоки событий подойдут в распределенных системах, потому что там иначе никак. Но не в мобильных приложениях, где надежность, скорость и простота отладки гораздо важнее чем написание абстрактных коней в вакууме, которые шлют события абы куда и принимаю абы откуда
github.com/NewtronLabs/IpcEventbus?utm_source=android-arsenal.com&utm_medium=referral&utm_campaign=5710
Если я встречу подобный подход в чьих-то исходниках, то сразу поставлю диагноз: "архитектура головного мозга". Без обид.
С точки зрения оторванной от реальности теории — может и не очень хорошо, что диалог ищет своего слушателя, но если вспомнить, что после восстановления система (андроид) сама создает компоненты, то это вполне нормально. Надо просто помнить, что активити/фрагменты/диалоги — независимые сущности, которые должны сами о себе позаботиться.
Так принято.
Я статью до конца не читал, только до этого момента, но у вас там, кажется, утечка будет. Потому при нормальной реализации вы создаете сильную ссылку в onAttach(), и обнуляете ее в onDetach(), а так у вас останется сильная ссылка и активити утечет. Нужно викреф делать.
Короче, вы велосипед ненужный сделали. Первоначальный вариант — лучший.
return App.get()
Апп-синглтон, конечно, не приведет к утечке, но это индикатор плохой архитектуры.
Можете показать пример, в котором по-вашему не обойтись без аппа-синглтона?
onAttach()
, нужно чистить в onDetach()
, чтобы не было утечки памяти. И в реальном коде это было. Я не стал это копировать сюда, так как это напрямую не относилось к теме статьи.В проекте, которым сейчас занимаюсь, с большущим легаси, как раз нужно было написать фрагмент, который бы мог возвращать результаты — кому-то через eventBus, кому-то через onActivityResult, кому-то через синглтоны (через даггер), где-то фрагмент бы открывался напрямую, где-то — с другой activity. При этом весь этот мусор во фрагмент тащить не хотелось, и ваше решение идеально подошло.
Обнаружение зависимостей Android компонентов