ImangazalievM/CleanArchitectureManifest

Место 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));

Добрый день.
Огромное спасибо Вам за разъяснения.

С уважением, Алексей.