[英]Requesting filesize and MIME type for a list of URLs in Android
在一个Android应用程序中,我有一个图像URL列表,如下所示:
List<String> urls = new ArrayList<String>(100);
urls.add("http://www.example.org/1.jpg");
urls.add("http://www.example.org/2.png");
urls.add("http://www.example.org/3.jpg");
urls.add("http://www.example.org/4.jpg");
urls.add("http://www.example.org/5.png");
urls.add("http://www.example.org/6.png");
urls.add("http://www.example.org/7.png");
urls.add("http://www.example.org/8.jpg");
urls.add("http://www.example.org/9.jpg");
urls.add("http://www.example.org/10.gif");
...
urls.add("http://www.example.org/100.jpg");
现在,我必须获取所有这些URL的文件大小和MIME类型,当然,这应该尽快完成。
我所做的是以下几点:
for (String url : urls) {
int fileSize;
try {
URLConnection urlConnection;
urlConnection = new URL(url).openConnection();
urlConnection.connect();
final String mimeType = urlConnection.getContentType();
final int fileSize = urlConnection.getContentLength();
// do something with those two pieces of information
}
catch (MalformedURLException e) {
continue;
}
catch (IOException e) {
// some special handling
}
}
但这非常慢。 这是因为它使用单个线程并一个接一个地请求URL,而Web浏览器始终总是一次访问多个文件,不是吗?
那么我怎样才能使其更快呢?
对于HttpClient
,我读到您应该重用实例,并且有一些方法可以在多线程环境中使用它们。
但是,我该如何使用URLConnection
或任何其他提供文件大小和MIME类型的类来做到这一点?
编辑:
这些映像并非全部位于同一主机上,而是仅分布在少数服务器上,例如100个映像分布在5个主机名上。
您可以使用几个线程或一次运行多个AsynTasks来完成这项工作吗? 您有什么需要注意的,例如回收URLConnection
对象等吗?
我不太确定如何使用多个线程共享任务列表(100个图像文件),然后再合并结果(MIME类型和文件大小)。 你能帮我吗?
将您的工作分成较小的部分,然后由工作Thread
处理:
工作Thread
:
public class Downloader extends Thread {
private final String mUrl;
private String mMimeType;
private int mFileSize;
public Downloader(String url) {
mUrl = url;
}
@Override
public void run() {
try {
URLConnection urlConnection;
urlConnection = new URL(mUrl).openConnection();
urlConnection.connect();
mMimeType = urlConnection.getContentType();
mFileSize = urlConnection.getContentLength();
} catch (IOException e) {
e.printStackTrace();
}
}
public String getMimeType() {
return mMimeType;
}
public int getFileSize() {
return mFileSize;
}
}
实例化,运行并等待工人:
ArrayList<String> urls = new ArrayList<String>(10);
// ...
ArrayList<Thread> threads = new ArrayList<Thread>(10);
for (String url : urls) {
Thread t = new Downloader(url);
threads.add(t);
t.start();
}
for (Thread t : threads) {
try {
// do not wait for other threads in main UI thread!
t.join();
//((Downloader) t).getMimeType();
//((Downloader) t).getFileSize();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
请务必注意等待工作Thread
在UI Thread
。
上面的答案仅应用于少数URL。 ThreadPool
可能不是必需的,因为Thread
通常会等待IO。
这是您要求的ThreadPool
答案。
它使用与上述示例相同的Downloader
类,但只有一个更改:生成Thread
是由ThreadPool
完成的,单个任务不再是真正的Thread
。 因此,让Downloader
实现Runnable
而不是扩展Thread
:
public class Downloader implements Runnable {
希望这是您想要的。
public class ThreadedDownloader {
private static final int KEEP_ALIVE_TIME = 1;
private static final TimeUnit KEEP_ALIVE_TIME_UNIT = TimeUnit.SECONDS;
private static int NUMBER_OF_CORES = Runtime.getRuntime().availableProcessors();
private LinkedBlockingQueue<Runnable> mDecodeWorkQueue = new LinkedBlockingQueue<Runnable>();
private ThreadPoolExecutor mDecodeThreadPool = new ThreadPoolExecutor(NUMBER_OF_CORES,
NUMBER_OF_CORES, KEEP_ALIVE_TIME, KEEP_ALIVE_TIME_UNIT, mDecodeWorkQueue) {
@Override
protected void afterExecute(Runnable r, Throwable t) {
super.afterExecute(r, t);
Downloader d = (Downloader) r;
// do something with finished Downloader d
// like saving it's result to some sort of list
// d.getMimeType();
// d.getFileSize();
if (mDecodeWorkQueue.isEmpty()) {
onAllDownloadsFinised();
}
}
};
/** Download a list of urls and check it's mime time and file size. */
public void download(List<String> urls) {
for (String url : urls) {
mDecodeThreadPool.execute(new Downloader(url));
}
}
/** Calles when all downloads have finished. */
private void onAllDownloadsFinised() {
// do whatever you want here
// update UI or something
}
}
我没有示例代码,但是您正在寻找HTTP动词HEAD 。 它检索标头(包括mime和content-length),而不传输内容主体。
该答案将更详细地介绍HEAD的功能。
我认为您已经解决了大部分(如果不是全部的话)解决方案。
这是我要做的:
1)使用Executors.newCachedThreadPool()发出头请求;
2)将响应存储在地图中
3)创建有效载荷图
4)使用AsyncTask实例加载真实图像
5)每个位图加载完成后,将结果存储在有效载荷图中
只是我的想法。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.