扩展函数不会创建新的Observable对象
我有kotlin和rxjava意想不到的行为。 我使用picasso创建了一个用于加载图像的扩展function
fun Picasso.loadBitmap(url: String) : Observable = Observable.create { 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 { t1, t2 -> RetryWrapper(t2.toLong(), t1) }) .flatMap { if(it.delay 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
被调用时,都会创建一个新的observable。 但我在日志中得到了这个
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
调用的observable都是一样的。 我需要他们有自己的观察,因为如果我不会,当重retryWhen
失败时,它不会继续下一个失败。 我希望这是有道理的。
把可观察的内部defer
或flatmap
不会改变任何东西。
编辑我的代码
override fun render(state: MainState) { map?.let { map -> val newMarkers: MutableList = 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 { t1, t2 -> RetryWrapper(t2.toLong(), t1) }) .flatMap { if(it.delay 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,只是为了看到更广泛的一点。 那么,在MODEL完成从服务器获取数据之后,VIEW,render中的函数将被触发。
你必须在这里小心。 这个关键字在
Log.d("picasso load bitmap", "me ${this}")
不针对Observable
而是接收者types。 在你的情况下, Picasso
。 你在me com.squareup.picasso.Picasso@c894e26
的日志里看到me com.squareup.picasso.Picasso@c894e26
好消息是,每次调用loadBitmap
,都会得到一个Observable
的新实例。 你可以检查这个:
val observable = picasso.loadBitmap(place.image_url) Log.d("observable for picasso", "$observable") observable.subscribeOn(Schedulers.io())...
所以你看,你总是在同一个picasso
实例上调用loadBitmap
,这就是为什么你会得到相同的输出。 但是,每个单独的调用loadBitmap
都会创建一个新的Observable
所以你的代码很好。