Pull to refresh
14
0
Матвей Мальков @lNevermore

User

Send message
Я с трудом читаю какие-то статьи, где вместо «Активити» или «Activity» написано «Активность» а вместо сабджекта «объект» или «субъект».

Без мутабельности и импрувментов можно было и обойтись в тексте, да. Но это транскрипт с записи речи, а с языка мне и не хочется их убирать, поэтому так и вышло.
Ну ладно, что уж вы) Я не приравнивал Rx к самому подходу. Конечно, это лишь одна из многих реализаций, тут я полностью с вами согласен.
Другое дело, что для Android все таки сильно чаще используется именно RxJava или RxKotlin или еще что из Rx.

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

Но соглашусь, что чаще говорят именно про RxJava и меньше про другие фреймворки и подходы.
На самом деле очень сложно поначалу вникнуть и понять, зачем все это нужно. Мне кажется, что некоторые люди просто ее используют, потому что это «модно», а не потому, что дает им какие-то выгоды.

Если говорить про понимание, то, возможно, саам стоит начать с лекций и видео каких-нибудь. Из довольно много и про Android и про iOS, про веб фронтенд и даже про бекенды. Там частенько бывают вещи, которые раскрывают всю суть реактивного подхода
Вроде как продукт называется ДВАгис, а сама компания до сих пор ДульГис
Я соглашусь с Артемом. Дело в том, что этого не называют конкретно в вакансии, но на собеседовании многие компании, которые использую всякие новый технологии, наверняка будут рады, если вы будете знать что-нибудь связанное с Rx. Не говоря о том, что самих проектов на ней под Android становится все больше и больше.
Сорри, я старался быть максимально понятным, не вышло.
Ага, уже понял, спасибо.

Это прям огорчило меня.
Да, про это тоже хотел написать. Не совсем понятно, почему «корпорация добра» заставляет своих покупателей думать о проводах, их характиристиках и толщине.
Возможно, что пользователей Apple это и норма.

Я привык, покупая телефон, получать все необходимое для его использования, а не заказывать с ebay или алиэкспресс.

Наушники, например, таковыми(необходимыми) не являются и я не против того, чтобы их не клали. Но такие вещи, как переходник с type-c на type-a в андроид мире, где повсеместно используется type-a — это не очень правильный ход, по моему мнению.
Спасибо за обзор.

Правильно ли я понял, что в коробке кабеля type-c — type-a не предусмотрено? Не очень понятно, как подключить телефон в компьютеру и использовать его для разработки Android приложений в таком случае.

Кажется, что это достаточно большой косяк.
Хорошая статья, приятно читается и написана хорошо, спасибо вам.

Хотел немного порассуджать про Subject. По моему мнению они выглядят как костыль над самими потоками. Потому что под источником подразумевается обычно замкнутая система, которая сама решает, как порождать ей элементы и когда это делать. И, как и любое костыль над контрактом, сабджекты провоцируют людей чаще их (сабджектов) использовать и само их использование иногда ведет к нарушению идеологии реактивных потоков:) Безусловно, бывает, что их применение оправдано. Обычно это делается в том случае, когда по-другому источник невозможно создать или в целях оптимизации.

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

Например, он может эммитить дату последнего айтема, чтобы загружать с этой даты новые, или adapter.getItemCount(), чтобы эммитить сразу оффсет, по которому идти, как у вас и сделано.
Что-то типа:

public final class ScrollObservable {
    public static Observable<Integer> from(final RecyclerView rv) {
        return Observable.create(subscriber -> {
            final RecyclerView.OnScrollListener sl = new RecyclerView.OnScrollListener() {
                @Override
                public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
                    if (!subscriber.isUnsubscribed()) {
                        final int position = getLastVisibleItemPosition();
                        final int limit = getLimit();
                        final int updatePosition = rv.getAdapter().getItemCount() - 1 - (limit / 2);
                        if (position >= updatePosition) {
                            subscriber.onNext(rv.getAdapter().getItemCount());
                        }
                    }
                }
            };
            rv.addOnScrollListener(sl);
            subscriber.add(Subscriptions.create(() -> rv.removeOnScrollListener(sl)));
        });
    }
}


В этом случае получается Обсервабл, который начинает бешено эммитить айтемы при достижении определеного порога. Чтобы это происходило всего один раз, нам не надо делать подписки и отписки от сабджектов или что-то еще, просто применяем distinctUntilChanged и получаем новые оффсеты только раз:

final Observable<Integer> offsetRequestObs = ScrollObservable.from(recyclerView).distinctUntilChanged();


Соответственно в onNext мы не будем запускать новый Observable, потому что это тоже не очень круто, тк они получаются оторваны от жизненного цикла родителя. Просто делаем switchMap и потом перенаправляем на ui, где обрабатываем:

offsetRequestObs.switchMap(offset -> getLoadingObservable(offset))
                .subscribeOn(Schedulers.from(BackgroundExecutor.getSafeBackgroundExecutor()))
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(loadNewItemsSubscriber);


В целом это решение делает то же самое, но, как мне кажется, оно лучше поддается расширению и это полноценный Observable, с котором можно делать все, что угодно. Кроме того, имеем связанный жизненный цикл потоков, что тоже важно.

Как я и говорил выше, сабджекты обычно зло и без них очень часто можно сделать лучше и лаконичнее. Не понимаю, почему их все часто используют. Кроме того, важным фактом тут является еще то, что мы не делаем нового наследника RecyclerView, но и в вашем примере можно добиться того же.
Хорошая статья, спасибо.

Согласен с 7voprosov про reduce, еще хотел отметить, что в примере у вас после concatMap идет map, и по сути map не нужен, можно вставить этот геттер прямо в concatMap, убрав лишний оверхэд и сделав код более коротким и более читабельным (на вкус и цвет, разумеется).
Полностью согласен с вами. Добавлю так же, что лучше создавать несколько тредпулов с меньшим количеством тредов.

Например, тредпул с CPU_COUNT/2 для работы с сетью, такой же для выполнения рутинных задач и FixedThreadPoolExecutor на 2-3 треда для выполнения очень приоритетных задач (коих должно быть не много по задумке).

Так проще регулировать работы обсерваблов, если их становится много, а так же позволяет приоритезировать задачи. Обычно это работает неплохо.
Именно. Убрал за ненадобностью в примере, а тип ссылки не поменял.
Да, разумеется, это описка. Спасибо.
Единственный метод, который возвращает не новый Observable, а Subscription — это метод subscribe()
Вы создали словарь со «значком». Создайте словарь с лямбдами. Как-то так:
let operationDictionary: Dictionary<String, (Double, Double) -> Double > = [ "+": {$0 + $1} , "x": {$0 * $1}]

Понимаю, что не так изящно, как "+", но лучше, чем явно заданная где-то вверху функция.
Хорошая обзорная статья, спасибо!)

Как java-related разработчик не могу не заметить, что немного похоже на Scala. Или мне просто кажется и это просто веяния современности.

Тем не менее, жду не дождусь, когда на нем можно будет писать полноценные приложения.
Ну и хорошо, это удобная фича, как по мне!
Я говорю про запуск голосом, Вы про это же? Я не говорю, что это уникальная фича, я лишь говорю, что она есть не во всех лаунчерах и мне ее не хватает.
Я говорил вот про этот.

Интересно, пол года назад точно нельзя было на стоковом киткате.

Information

Rating
Does not participate
Location
Новосибирск, Новосибирская обл., Россия
Date of birth
Registered
Activity