假设您从我在此答案中发布的代码开始,并使用您在此问题中显示的代码从 URL 列表中下载图像,那么您应该能够通过以下更改实现延迟图像加载:
创建一个在下载完成时收到通知的侦听器接口:
public interface DownloadListener {
// invokes if download success
public void downloadSuccess(Bitmap bitmap);
// invokes if download failed
public void errorOccured();
}
然后,将代表一个列表行的 Manager 子类CustomListRow
修改为实现此接口,并_thumb
在下载完成时更新图像:
public class CustomListRow extends Manager implements DownloadListener, FieldChangeListener {
public void downloadSuccess(final Bitmap img) {
_data.setThumb(img);
// make sure bitmap is updated on the UI / main thread
UiApplication.getUiApplication().invokeLater(new Runnable() {
public void run() {
_thumb.setBitmap(img);
}
});
}
public void errorOccured() {
// TODO: handle error
}
然后,您需要添加一些代码来创建所有线程以在后台下载图像,并DownloadListeners
在图像下载完成时通知您。您可以决定在哪里执行此操作。在我的示例中,我将在我的ListScreen
类中执行此操作,在其中实例化ListRander
数据对象和CustomListField
:
for (int i = 0; i < numberOfItem; i++) {
ListRander lr = new ListRander("Product Name " + i, icon); // icon is placeholder for thumbnail image
data.addElement(lr);
}
final CustomListField list = new CustomListField(data);
add(list);
list.setChangeListener(this);
pool = new ThreadPool(3); // 3 concurrent download threads
for (int i = 0; i < numberOfItem; i++) {
final int row = i;
// create a new runnable to download the next image, and resize it:
pool.assign(new Runnable() {
public void run() {
try {
String text=object[row].getJSONArray("UrlArray").getString(0).toString();
EncodedImage encodedImg = JPEGEncodedImage.encode(connectServerForImage(text), quality); //connectserverForImage load Images from server
EncodedImage logoThumbnail = sizeImage(encodedImg, Display.getWidth(), Display.getHeight()-100);
list.getRow(row).downloadSuccess(logoThumbnail.getBitmap());
} catch (Exception e) {
e.printStackTrace();
list.getRow(row).errorOccured();
}
}
}
});
}
您可以在ListScreen
构造函数中执行此操作,或者在您拥有object[]
URL 数组时执行此操作。
您需要添加一个新方法CustomListField
:
public CustomListRow getRow(int row) {
return (CustomListRow)getField(row);
}
上面的代码还需要添加一个成员变量(in ListScreen
)来创建线程池:
private ThreadPool pool;
此线程池实现基于此处的本教程,进行了非常小的修改,只需将ArrayList
(在 BlackBerry Java 上不可用)更改为Vector
... 并删除对Thread#destroy()
. 您需要将该教程的 、 和 类复制ThreadPool
到WorkerThread
您Done
的项目中。我展示的上述示例创建了一个包含 3 个线程的线程池。在单 CPU 智能手机上,2 或 3 个线程可能足以满足您的需求。 如果您想为您的应用程序获得完美数量的线程,请在此处阅读更多信息。
注意:如果可能的话,如果您下载的图片大小正好适合您的应用程序,通常可以提高性能,而不是让网络负担更大的图片,然后在您的应用程序中调整它们的大小。但是,我意识到这取决于对图像的网络服务器进行一些控制,而您可能没有。只是以后优化的想法。