Comments 23
человек передвинул карту, то предыдущий запрос теряет актуальность и мы должны запросить новые точки.
Конечно же это не так :)
Это приводит к тому, что при сдвиге карты надо загрузить только дельту по сдвигу, дополнив, а не заменив, данные.
В общем в JS API этот момент немного самим API покрыт, под андроидом судя по всему — нет.
Так уж получилось — но Яндекс.Недвижка ну совсем не умеет работать с данными карты. А принцип там очень простой — при сдвиге карты данные (в уже видимой области) НЕ должны меняться.
Далее, чтобы избежать моргания пинов на карте, берётся пересечение множества уже загруженных точек с теми, которые только что получили. Таким образом, пины, которые вышли из области видимости, удаляются, которые появились — добавляются на карту.
А идея с загрузкой дельты вводит дополнительную сложность, поскольку надо считать эту дельту, объединять её результаты с текущими, это что касается клиента. С точки зрения сервера, не факт, что поиск в дельте будет быстрее, чем во всей области + с кластеризацией сложнее.
Вот смотрели вы на краешек Москвы, и все данные были там. Потому что их много.
А потом подвинули на пиксель — и картинка полностью изменилась. Потому что данные обычно запрашивают с никим лимитом, и раньше этот лимит «тратился» на центр города.
У меня (к счастью? к сожалению?) нет возможности проверить как работает андроид приложение, но в вебе сейчас все с этим плохо, и всегда так и было – информация приходит не равномерно.
Сейчас есть два «хороших» решения проблемы — или загрузка данных дискретными «тайлами». В том числе там нет понятия «запрос, который еще не успел выполнится» — тайл в любом случае может оставаться актуальным, и пускай продолжает загружаться. Либо ограничения лимита через серверную кластеризацию, по тем же Z-кодам.
PS: Z-code, он же Morton code, может быть заменен Geocode или hilbert code. В общем 1D spatial index.
Опять же — если хранить данные в Z кодах, а запрашивать в тайлах — запрос превращается в поиск в 1D интервале и начинает работать чуть чуть быстрее.
У меня нет ссылки на «не матан», а на понятное обьяснение задачи, но есть видео.
Ну и конечно же все эти мозги без особых проблем спрячутся за фасадом функции getClusters, а сам пример с RxJS очень понравился.
Когда я похожую проблему решал много лет назад для схожего по тематике сайта gdeetotdom – мне первое решение завернули сразу именно из-за «раздражающих анимашек» неустойчивой кластеризации.
Цитата <a https://github.com/ReactiveX/RxJava/wiki/Creating-Observables">отсюда
create( ) — advanced use only! create an Observable from scratch by means of a function, consider fromEmitter instead
fromEmitter() — create safe, backpressure-enabled, unsubscription-supporting Observable via a function and push events.
Буквально на неделе в чате полдня выясняли, почему у человека после возникновения ошибки половина цепочки вызовов продолжала работать (до первого flatMap, как потом выяснилось), а другая половина нет. Также не работал retry. Причиной оказалось некорректное использование Observable.create, сначала был пропущена а потом не туда вставлена проверка subscriber.isUnsubscribed.
Согласен, fromEmitter
выглядит проще и надёжнее.
Сам его до этого не использовал, потому что в тех редких местах где использовал Observable.create
проблем с backpressure не было. А в других использовал Observable.SyncOnSubscribe
и Observable.AsyncOnSubscribe
.
Можно ли было внутри FilterHolder
'a использовать BehaviorSubject
вместо PublishSubject
'а и сохранения последнего элемента последовательности "вручную"?
Данный доклад абсолютно очень misleading.
В чем проблема Message.sendDelayed()
? Как будто у нас есть другие способы передать управление в main поток из других потоков. От того, что они передвинули переход в main поток чуть повыше в бизнес логике, смысл не поменялся, в каком-то месте идет передача управления из какого-то потока через Handler
и отрисовка данных. Не хотите NPE — не делайте рейс кондишенов :)
К NPE вы можете прийти только если вы сами обнулите ссылки, с которыми работаете в коллбеках, до того как отпишитесь от Subscription
, при таком коде у вас будет рейс кондишен. То есть это чисто логическая ошибка при написании кода, а не "подарок" от Android Framework.
Магии никакой нет, GC/VM за вас ссылки не обнуляет, если хотите какие-то ссылки обнулить руками (в 99% это ошибка в дизайне, тк у нас рантайм с GC), то делайте это вместе с subscription.unsubscribe()
(порядок не важен, тк как правило, вы делаете это в том же потоке, в котором потом будет работать коллбек, но если сложно про это думать, то чуть ниже написано более общее правило).
Железобетонное правило: делайте subscription.unsubscribe()
как можно раньше (до обнулления ссылок, etc), тогда проблем не будет.
Укрощаем асинхронные процессы в Android с RxJava. Опыт Яндекса