我正在编写一个涉及自定义搜索许多图像的程序。当用户输入他们的搜索标准时,从高速缓存或服务器检索相应的图像。我有一个JTable,显示相应图像的链接。当用户点击链接时,图像显示在JPanel上。单击链接时,我可以从硬盘驱动器中读取图像,但速度不如我想的那么快。加载它需要几秒钟。我尝试过创建一个BufferedImages数组,但是如果搜索返回了很多结果,那么我就去了。我想知道在单击链接时使图像显示更快的最佳方法是什么。
这是我如何获得图像...
Public void getFile(String fileName){
File file = new File("./cache/"+fileName);
boolean exists = file.exists();
BufferedImage returnImage =null;
if(exists){
try {
returnImage = ImageIO.read(file);
System.out.println("Found In Cache!");
} catch (IOException|IndexOutOfBoundsException e) {
try {
if(fileName != null){
returnImage = downloadImage(fileName);
System.out.println("Found ON Server :(");
}
} catch (IOException |IndexOutOfBoundsException ex) {
// TODO Auto-generated catch block
ex.printStackTrace();
}
}
}else{
try {
if(fileName != null){
returnImage = downloadImage(fileName);
System.out.println("Found ON Server :(");
}
} catch (IOException |IndexOutOfBoundsException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
return returnImage;
}
}
这就是我把它们放在一个数组中的地方......
BufferedImage[] images = new BufferedImage[numOfSearchResults];
for(SearchResult r: results){
images[i] = imageCache.getFile(r.imageName);
}
基本上我只是想知道什么是最好的方法来预先加载图像而不用oom。在此先感谢
答案 0 :(得分:3)
从磁盘加载图像需要几秒钟,这听起来不合理,除非图像真的非常,真的很大(10百万像素或更多)。首先确定实际花费的时间。
对于缓存,您可以使用java.lang.ref.SoftReference保存对您加载的每个图像的引用 - 这允许在运行OOM之前对图像进行垃圾收集。 如果真的不可避免,我将使用多层缓存系统,第一级使用内存中的SoftReferences,而基于服务器的映像则使用额外的磁盘缓存。在查找图像时,首先检查内存中的缓存,如果没有找到任何内容,则检查磁盘缓存,如果仍未找到,则以常规方式加载图像。
答案 1 :(得分:2)
不要加载所有/太多图像,在当前索引之前加载几个图像,并在当前索引之后耦合图像。
将图像加载器实现为一个不同的线程,当用户正在观看当前加载的图像时,该线程不会阻止主执行线程并加载其他图像。
答案 2 :(得分:0)
您可以打开所有图像的InputStream并关闭用户未点击的图像,只需使用您需要的图像。
通过这种方式,您无需缓冲所有图片,但在用户点击时已经“触手可及”。
但是正如@Robin正确评论的那样,加载平均大小的图片真的不需要很长时间。
我不确定这对你的表现有多大帮助,但根据你的情况,它可以。
答案 3 :(得分:0)
如果您不需要全尺寸图像,我会在加载时缩小它们以减少内存量。你必须记住,内存中的图像加载不再被压缩。
如果您可以控制源图像,我会考虑生成缩略图以帮助它们加载更快。我们使用200x200&的缩略图。即使在基于SMB的共享中,它们也需要不到一秒的时间来加载