我尝试进行多个并发HTTP GET调用,这些调用可能会在不同的时间后返回响应。
获得数据后,我使用它为ListView创建自定义适配器。由于存在NullPointerException的高风险,因此在尝试创建适配器之前,我需要确保所有数据都存在。
HTTP调用目前使用AsyncTask完成,这样可以方便地在后台执行,稍后调用UI线程来更新视图。但它们并不是并发的 - 每个呼叫都是在前一个呼叫结束后执行的。
我正在努力解决的问题是确保所有HTTP调用在创建适配器之前都返回了响应,同时仍保持并发。
有没有办法运行多个并发网络调用,并且在所有并发HTTP调用完成后让onPostExecute方法执行此操作?
或者我是否需要使用更复杂的线程,锁等?
答案 0 :(得分:4)
CountDownLatch
可能会为您解决问题。您使用计数初始化它,然后在每次HTTP调用后调用countDown()
,它会立即返回。在onPostExecute
侧,await()
阻止countDown()
被调用count
次。
所以:
CountDownLatch
构造函数中的HTTP调用数构建AsyncTask
latch.countDown()
onPostExecute
的线程调用latch.await()
,它将阻塞,直到所有上述线程都完成了他们的HTTP调用以上内容将会奏效(每个countDown()
和await()
返回之间会发生之前的关系),但还有另一种方式。
在Callable<Response>
中换行每个HTTP呼叫,并将其提交给ExecutorService
;它会立即返回Future<Response>
,然后您可以将其提供给定义onPostExecute
的对象。该方法可以获得Response r = future.get()
的实际响应,这将阻止直到特定的可调用完成。如果您为所有HTTP调用执行此操作,那么在为每个期货调用futureWhatever.get()
之后,您将确保HTTP调用已完成。
这种方法的一个优点是onPostExecute
在完成所有HTTP调用之前不必阻塞;它可以取得进展,直到那一刻它需要的那个完成。例如,如果确实如此:
Future callA = httpA.get();
processCallA(callA); // this could take a while
Future callB = httpB.get();
...
...然后只要HTTP调用B已经完成,processCallA
就可以完成它,只要HTTP调用A已经完成。