自定义列表与延迟加载

时间:2013-10-12 06:55:10

标签: blackberry lazy-loading custom-lists

我已经成功实现了这样的自定义列表中的延迟加载 enter image description here

我使用的代码在这里:Custom List With Images in Blackberry 在链接的问题中,我定位心脏图标的y坐标,我解决了链接问题的问题。

 if (logoThumbnailImage != null
     && logoThumbnailImage.length > index
     && logoThumbnailImage[index] != null) {

       EncodedImage img = logoThumbnailImage[index];
       graphics.drawImage(0, y + 10, Display.getWidth(),
                          Display.getHeight() - 100, img, 0, 0, 0);
       graphics.drawImage(300,
                          y+400,
                          heart.getWidth(), heart.getHeight(), heart,
                          0, 0, 0);

现在我想处理两者的点击事件;也就是说,对于列表行单击和单击心脏

为此,我看到了@Nate在Custom List Field click event写的帖子。但在该代码中,图像不是从服务器加载的,而是静态图像。我想用我的代码实现@Nate的代码(这是延迟加载)。

如果您有任何想法,请建议我该怎么做。在此先感谢

2 个答案:

答案 0 :(得分:2)

假设您从我发布的in this answer代码开始,并使用您在this question to download images from a list of URLs中显示的代码,那么您应该能够通过以下更改实现延迟图像加载:

创建listener interface that gets notified when downloads complete

public interface DownloadListener {
   // invokes if download success
   public void downloadSuccess(Bitmap bitmap);

   // invokes if download failed
   public void errorOccured();
}

然后,代表一个列表行CustomListRow的Manager子类被修改为实现此接口,并在下载完成时更新_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。您可以决定 where 来执行此操作。在我的示例中,我将在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[]数组网址时执行此操作。

您需要向CustomListField添加新方法:

public CustomListRow getRow(int row) {
    return (CustomListRow)getField(row);
}

上面的代码还需要添加一个成员变量(在ListScreen中)来创建一个线程池:

private ThreadPool pool;

此线程池实现基于this tutorial here,只需稍加修改,只需将ArrayList(BlackBerry Java上不可用)更改为Vector ...并删除对{ Thread#destroy()。您需要将该教程的ThreadPoolWorkerThreadDone类复制到您的项目中。上面的示例我展示了一个3个线程的线程池。在单CPU智能手机上,2或3个线程可能适合您的需求。 Read more here如果您想获得应用程序的完美线程数。

注意:如果可能,您通常可以提高性能,如果您下载的应用程序大小恰好适合您的应用程序,而不是使用较大的图像加载网络,然后在应用程序内调整它们的大小。但是,我意识到这取决于对图像的Web服务器进行一些控制,而您可能没有。只是想以后的优化。

答案 1 :(得分:1)

我确信我在旅行中看到了这个问题的一个很好的答案,但现在找不到。我建议在这里查看BB论坛: http://supportforums.blackberry.com/t5/Java-Development/bd-p/java_dev 因为那里有类似的问题。

目前,只需要了解您需要做的事情:

  1. 创建一个可运行处理下载的图像下载 - 您已经在之前的代码中完成了此操作。
  2. 使用Observer模式(在互联网上搜索),以便BitmapField成为完成图像下载的Observer。因此,当下载图像时,Runnable会调用观察者,然后观察者可以更新位图。
  3. 使用具有有限数量线程的线程池(我会说3),这样您就不会同时启动整个图像下载。在互联网上搜索有关线程池的信息,以帮助实现此功能。您之前的示例中没有完成此步骤,并且您可以运行所有下载,但我希望在某个阶段会失败。
  4. 将这些放在一起,你就有了解决方案。我知道并非无足轻重。祝好运。