Функция расширения не создает новый объект Observable

У меня неожиданное поведение с котлин и rxjava. Я создаю функцию расширения для загрузки изображения с помощью пикассо

fun Picasso.loadBitmap(url: String) : Observable<Bitmap> = Observable.create<Bitmap> { emitter -> Log.d("picasso load bitmap", "me ${this}") try { val bitmap = load(url).centerCrop() .resize(100, 100) .transform(CircleTransformer()) .get() emitter.onNext(bitmap) emitter.onComplete() } catch (e: IOException) { emitter.onError(e) } } 

Я называю это несколько раз с близким интервалом (почти в одно и то же время), как это,

 picasso.loadBitmap(place.image_url) .subscribeOn(Schedulers.io()) .retryWhen { error -> error.zipWith(Observable.range(1, 5), BiFunction<Throwable, Int, RetryWrapper> { t1, t2 -> RetryWrapper(t2.toLong(), t1) }) .flatMap { if(it.delay < 4){ Log.d(TAG, "retry no. ${it.delay} for ${place.image_url}") Observable.timer(it.delay * 5, TimeUnit.SECONDS) } else { Log.d(TAG, "DMD ${place.image_url}") Observable.error { it.error } } } } .subscribe ( { bitmap -> markers.find { it.place.id == place.id }?.let { it.marker.icon = IconFactory.getInstance(context).fromBitmap(bitmap) } }, { Log.e(TAG, "error decoding ${place.image_url}", it) }) 

Я ожидаю, что каждый раз, когда loadBitmap будет вызван, он создаст новое наблюдаемое. Но я получил это в журналах

 09-28 11:17:00.022 31694-32276/? D/picasso load bitmap: me com.squareup.picasso.Picasso@c894e26 09-28 11:17:00.068 31694-32277/? D/picasso load bitmap: me com.squareup.picasso.Picasso@c894e26 09-28 11:17:00.069 31694-31959/? D/picasso load bitmap: me com.squareup.picasso.Picasso@c894e26 09-28 11:17:00.108 31694-32278/? D/picasso load bitmap: me com.squareup.picasso.Picasso@c894e26 09-28 11:17:00.112 31694-32251/? D/picasso load bitmap: me com.squareup.picasso.Picasso@c894e26 09-28 11:17:00.125 31694-32260/? D/picasso load bitmap: me com.squareup.picasso.Picasso@c894e26 09-28 11:17:00.162 31694-31794/? D/picasso load bitmap: me com.squareup.picasso.Picasso@c894e26 09-28 11:17:00.192 31694-32280/? D/picasso load bitmap: me com.squareup.picasso.Picasso@c894e26 09-28 11:17:00.195 31694-32279/? D/picasso load bitmap: me com.squareup.picasso.Picasso@c894e26 09-28 11:17:00.219 31694-32281/? D/picasso load bitmap: me com.squareup.picasso.Picasso@c894e26 09-28 11:17:04.828 31694-32262/? D/picasso load bitmap: me com.squareup.picasso.Picasso@c894e26 09-28 11:17:14.885 31694-31793/? D/picasso load bitmap: me com.squareup.picasso.Picasso@c894e26 09-28 11:17:29.928 31694-32269/? D/picasso load bitmap: me com.squareup.picasso.Picasso@c894e26 

Наблюдаемый одинаковый для всех вызовов loadBitmap . Мне нужно, чтобы у них было собственное наблюдение, потому что, если я не буду, когда retryWhen не удастся, он не retryWhen к следующему сбою. Надеюсь, это имеет смысл.

Помещение наблюдаемого внутри defer или flatmap ничего не изменит.

ИЗМЕНИТЬ мой код

 override fun render(state: MainState) { map?.let { map -> val newMarkers: MutableList<PlaceMarker> = mutableListOf() for(place in state.places) { var placeMarker = placeMarkers.find { it.place.id == place.id } if(placeMarker != null && map.markers.contains(placeMarker.marker)) { newMarkers.add(placeMarker) placeMarkers.remove(placeMarker) } else { if(placeMarker != null) placeMarkers.remove(placeMarker) val option = MarkerOptions() option.position = LatLng(place.latitude, place.longitude) option.snippet = place.name placeMarker = PlaceMarker(place, map.addMarker(option)) newMarkers.add(placeMarker) picasso.loadBitmap(place.image_url) .subscribeOn(Schedulers.io()) .retryWhen { error -> error.zipWith(Observable.range(1, 5), BiFunction<Throwable, Int, RetryWrapper> { t1, t2 -> RetryWrapper(t2.toLong(), t1) }) .flatMap { if(it.delay < 4){ Log.d(TAG, "retry no. ${it.delay} for ${place.image_url}") Observable.timer(it.delay * 5, TimeUnit.SECONDS) } else { Log.d(TAG, "DMD ${place.image_url}") Observable.error { it.error } } } } .subscribe ( { bitmap -> placeMarkers.find { it.place.id == place.id }?.let { it.marker.icon = IconFactory.getInstance(context).fromBitmap(bitmap) bitmap.recycle() } }, { Log.e(TAG, "error decoding ${place.image_url}", it) }) } } placeMarkers.forEach { it.marker.remove() } placeMarkers.clear() placeMarkers.addAll(newMarkers) } } 

Я использую MVP, просто для вас, чтобы увидеть немного шире. Таким образом, это функция внутри VIEW, рендеринг будет запущен после того, как MODEL завершит получение данных с сервера.

Вы должны быть осторожны. Ключевое слово this в

 Log.d("picasso load bitmap", "me ${this}") 

не ориентируется на Observable но тип приемника. В вашем случае Picasso . Вы видите, что в вашем журнале me com.squareup.picasso.Picasso@c894e26

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

 val observable = picasso.loadBitmap(place.image_url) Log.d("observable for picasso", "$observable") observable.subscribeOn(Schedulers.io())... 

Итак, вы видите, вы вызываете loadBitmap всегда на одном экземпляре picasso , поэтому вы получаете тот же результат для этого класса. Но каждый индивидуальный вызов loadBitmap создает новый Observable

Так что ваш код в порядке.

Intereting Posts
groupValues ​​возвращает только последнее появление повторяющегося шаблона Как издеваться над реактивным репозиторием, который возвращает Observable Одновременно создаются два объекта SQLiteDao, один из которых не создает таблицу при выполнении Helper Обрезающий наблюдательный делегат Клавиатура скрывает BottomSheetDialogFragment Как правильно обрабатывать перспективу с нулевой переменной в котлин? Котлин, когда () локальное переменное введение Как я могу использовать kotlin-maven-plugin под jdk1.7? Объявление об отказе от рекламы Kotlin REPL не работает с Pair значение переменной получает значение null в модификации Как создать кнопку в Kotlin, которая открывает новую активность (Android Studio)? Использование Kotlin и Firebase для запуска sendEmailVerification с обратным вызовом onAuthStateChanged Перехват метода перегрузки, полностью переопределяющий метод Async Spring Boot с использованием Kotlin не работает Как фильтровать и отображать 2D IntArray в набор с использованием потоков