我看过很多例子,它们似乎都用不同的方式解决这个问题。基本上我只想要最简单的方法来发送请求,而且不会锁定主线程并且可以取消。
同时我们还有(至少)两个HTTP库可供选择,java.net.* (如HttpURLConnection)和org.apache.http.*。
是否有关于最佳实践的共识?
我看过很多例子,它们似乎都用不同的方式解决这个问题。基本上我只想要最简单的方法来发送请求,而且不会锁定主线程并且可以取消。
同时我们还有(至少)两个HTTP库可供选择,java.net.* (如HttpURLConnection)和org.apache.http.*。
是否有关于最佳实践的共识?
Android 1.5 SDK引入了一个新类,AsyncTask,旨在使在后台线程上运行任务并将结果传递到UI线程变得更加简单。在Android Developers Blog中给出的示例说明了如何使用它的基本思想:
public void onClick(View v) {
new DownloadImageTask().execute("http://example.com/image.png");
}
private class DownloadImageTask extends AsyncTask {
protected Bitmap doInBackground(String... urls) {
return loadImageFromNetwork(urls[0]);
}
protected void onPostExecute(Bitmap result) {
mImageView.setImageBitmap(result);
}
}
doInBackgroundThread
方法在一个独立的线程上被调用(由线程池的 ExecutorService
管理),并将结果传递给在 UI 线程上运行的 onPostExecute
方法。您可以调用 AsyncTask
子类的 cancel(boolean mayInterruptIfRunning)
方法来取消正在运行的任务。
至于使用java.net
或org.apache.http
库进行网络访问,这取决于您。我发现当简单地尝试发出一个GET
请求并读取结果时,java.net
库非常好用。但是,org.apache.http
库允许您几乎可以对HTTP
做任何事情,但它们可能更难使用,并且我发现它们在 Android 上性能不如简单的GET
请求。
事实上,AsyncTask的设计存在一些缺陷,使其在网络应用方面并不十分实用。一个简单的例子是:只要你旋转设备,你就会失去AsyncTask和Activity之间的链接。
请参考这个线程:您将看到AsyncTask还很容易造成内存泄漏。
AsyncTask文档已经很明确了:AsyncTask只适用于短时间的任务, 很明显,网络并不属于这一类别。
因此,我强烈建议您查看RoboSpice。这个库专门为异步网络设计,非常强大且实用。 如果您只有几秒钟的时间来说服您,请查看这个信息图表。
RoboSpice还在商店里提供一个演示应用程序:RoboSpice Motivations,它将深入解释关于Android上异步网络的一切。
如果使用一个引用了静态保留Fragment(没有UI)的AsyncTask
,放在Activity或另一个Fragment中,这会怎样呢?没有内存泄漏,在单独的线程中进行优雅的异步操作,不会丢失对象引用。
我认为对于http请求来说这应该没问题,但对于文件上传/下载就不是很好。如果你仔细阅读,有一句话:
如果您需要长时间运行线程,强烈建议使用java.util.concurrent包提供的各种API,如Executor、ThreadPoolExecutor和FutureTask。
但他们没有提到,使用单独的线程作为服务也是一个不错的选择。这意味着可以在后台继续执行任务,无论用户做什么。(例如,如果他上传某个文件,你不想因为他离开了活动而停止这个过程)
这里有示例 - 找到RetainedFragment.java
这里有AsyncTask。