Место BroadcastReceivers в Clean Arcitecture
AlekseiPecherei opened this issue · 2 comments
Добрый день.
Прежде всего, хочу поблагодарить за хорошо изложенный и красиво оформленный материал.
Подскажите, где, в контексте Чистой Архитектуры, следует размещать BroadcastReceiver-ы?
Исследуя этот вопрос, я нашел совершенно противоположные реализации.
В первом случае, ресивер относят к View (располагается в Activity/Fragment) и в методе onReceive() делегируют intent в presenter.
По другой точке зрения, ресивер является компонентом domain слоя.
у третьих, ресивер находится в презентере.
Подскажите, пожалуйста, в какую сторону копать?
Если возможно, с примером
Здравствуйте .
Слой domain ничего не должен знать об используемых фреймворках или библиотеках, в том числе и о компонентах Android, поэтому размещение в нем BroadcastReceiver'а будет противоречить принципам Clean Architecture. По этой же причине его нельзя использовать в Presenter'е.
Сам BroadcastReceiver лучше разместить в слое data и использовать в реализации Repository. Вопрос лишь в том, где обрабатывать получаемые уведомления. Если обработка происходит в Repository, то здесь все понятно. Если же вы хотите получать события в Presenter'е, то вам нужно создать метод в Repository, который возвращает Observable. Например, мы хотим отслеживать статус подключения к интернету:
public class SomeRepositoryImpl implements SomeRepository {
private Context context;
@Inject
public SomeRepositoryImpl(Context context) {
this.context = context;
}
public Observable<Boolean> getNetworkStateChangeListener() {
return Observable.create(emitter -> {
final BroadcastReceiver receiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
boolean isConnected = ...;
emitter.onNext(isConnected);
}
};
IntentFilter networkStatusFilter = new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION);
context.registerReceiver(receiver, networkStatusFilter);
emitter.setCancellable(() -> {
if (Looper.getMainLooper() == Looper.myLooper()) {
context.unregisterReceiver(receiver);
} else {
final Scheduler.Worker inner = mainThread().createWorker();
inner.schedule(() -> {
context.unregisterReceiver(receiver);
inner.dispose();
});
}
});
});
}
}
Далее нужно создать точно такой же метод у Interactor'а, который дергает данный метод у репозитория.
public class SomeInteractor {
private SomeRepository someRepository;
public Observable<Boolean> getNetworkStateChangeListener() {
return someRepository.getNetworkStateChangeListener();
}
}
Осталось подписаться на Observable в Presenter'е и начать получать уведомления:
someInteractor.getNetworkStateChangeListener()
.subscribe(isConnected-> Log.d("NetworkState", "isConnected: " + isConnected));
Добрый день.
Огромное спасибо Вам за разъяснения.
С уважением, Алексей.