上QQ阅读APP看书,第一时间看更新
1.2.4 复杂分支
我们可以为同步的逻辑添加分支甚至循环操作,但对于异步的逻辑而言,想要做到这一点就相对困难了,如代码清单1-11所示。
代码清单1-11 同步循环
val bitmaps = urls.map { syncBitmap(it) }
调用syncBitmap可以同步获取一个Bitmap实例,并且很容易就能写出批量同步获取多个Bitmap实例的逻辑,如代码清单1-11所示。我们甚至还可以很方便地用一个try...catch来捕获这其中出现的所有异常。
而对于asyncBitmap而言呢?由于需要将所有的结果整合起来,因此我们还需要用到一些同步工具,见代码清单1-12。
代码清单1-12 异步循环
val countDownLatch = CountDownLatch(urls.size) val map = urls.map { it to EMPTY_BITMAP } .toMap(ConcurrentHashMap<String, Bitmap>()) urls.map { url -> asyncBitmap(url, onSuccess = { map[url] = it countDownLatch.countDown() // ... ② }, onError = { showError(it) countDownLatch.countDown() //... ③ }) } countDownLatch.await() //... ① val bitmaps = map.values
这段程序会在①的位置阻塞,直到所有回调的②或③位置执行之后才会继续执行。程序的执行流程如图1-6所示。
图1-6 异步循环结果映射
如果大家不熟悉CountDownLatch,一时间可能很难明白这段代码的执行流程。没关系,我们知道它很复杂就够了。
提示 EMPTY_BITMAP是一个空的Bitmap对象,用来充当空对象。这样做是因为ConcurrentHashMap中的value不能为null。