BlackBerry中的ListField中是否有用于加载图像的图像的LazyLoader?

时间:2012-12-13 11:37:35

标签: blackberry blackberry-simulator image-loading

我是BlackBerry开发的新手。但是关于android的好处。

我想在ListField中加载来自服务器的图像。

我已经实现了类似下面的代码,但没有取得成功:

   package mypackage;


public class TempScreen extends MainScreen implements ListFieldCallback{
    Bitmap[] images=null;
    private ListField mylist;
    private static Bitmap _bitmap;
    private ImageDownloader downloader;
    int size = 0;
    String[] urls={
            "http://www.kentnews.co.uk/polopoly_fs/damian_lewis_at_port_lympne_wild_animal_park_c_taf_1_1738362!image/2626063106.jpg_gen/derivatives/landscape_225/2626063106.jpg",
            "http://www.kentnews.co.uk/polopoly_fs/damian_lewis_at_port_lympne_wild_animal_park_c_taf_1_1738362!image/2626063106.jpg_gen/derivatives/landscape_225/2626063106.jpg",
            "http://www.kentnews.co.uk/polopoly_fs/damian_lewis_at_port_lympne_wild_animal_park_c_taf_1_1738362!image/2626063106.jpg_gen/derivatives/landscape_225/2626063106.jpg",
            "http://www.kentnews.co.uk/polopoly_fs/damian_lewis_at_port_lympne_wild_animal_park_c_taf_1_1738362!image/2626063106.jpg_gen/derivatives/landscape_225/2626063106.jpg"};
    public TempScreen()
    {


        images=new Bitmap[urls.length];
        size = urls.length;
        mylist = new ListField();
        mylist.setCallback(this);
        mylist.setSize(4);
        mylist.setRowHeight(getFont().getHeight() * 3);
        add(mylist);
        Thread downloader=new Thread(new ImageDownloader());
        downloader.start();

    }


    public void drawListRow(ListField listField, Graphics graphics, int index,
            int y, int width) {

        if(images[index]==null)
         {
             //Load placeholder image
            _bitmap = Bitmap.getBitmapResource("close_btn.png");// load some bitmap
            // of your choice
            // here
         }
         else
             //Load Bitmap
            _bitmap = images[index]; 

        graphics.drawText("row details", 100, y + 30);
        //graphics.drawBitmap(0, y, _bitmap.getWidth(), _bitmap.getHeight(),_bitmap, 0, 0);
        mylist.invalidate(index);
    }

    public class ImageDownloader implements Runnable
    {
        public void run()
        { 
            for(int i=0; i<size;i++)
            { 
                 if(images[i]==null) 
                 { 
                      images[i]=connectServerForImage(urls[i].toString());//replace downloadImage method to whatever method       you have to download the bitmap from url 
                      UiApplication.getUiApplication().invokeLater(new Runnable(){
                          public void run()
                          {
                              mylist.invalidate();
                          }
                      });
                  }
             }
        }
    }
    public Object get(ListField listField, int index) {
        // TODO Auto-generated method stub
        return null;
    }
    public int getPreferredWidth(ListField listField) {
        // TODO Auto-generated method stub
        return 0;
    }
    public int indexOfList(ListField listField, String prefix, int start) {
        // TODO Auto-generated method stub
        return 0;
    }
    public static Bitmap connectServerForImage(String url) {
        HttpConnection httpConnection = null;
        DataOutputStream httpDataOutput = null;
        InputStream httpInput = null;
        int rc;
        Bitmap bitmp = null;
        try {
            // httpConnection = (HttpConnection)
            // Connector.open(url+";interface=wifi");
            httpConnection = (HttpConnection) Connector.open(url);
            rc = httpConnection.getResponseCode();
            // System.out.println("===============================");
            Dialog.alert("beore if condition");
            if (rc == HttpConnection.HTTP_OK) {

                System.out.println(" ============= IN FUNCTION. . . . .");
                httpInput = httpConnection.openInputStream();
                InputStream inp = httpInput;
                byte[] b = IOUtilities.streamToBytes(inp);
                EncodedImage hai = EncodedImage.createEncodedImage(b, 0,
                        b.length);
                bitmp = hai.getBitmap();
            } else {
                throw new IOException("HTTP response code: " + rc);
            }
        } catch (Exception ex) {
            System.out.println("URL Bitmap Error........" + ex.getMessage());
        } finally {
            try {
                if (httpInput != null)
                    httpInput.close();
                if (httpDataOutput != null)
                    httpDataOutput.close();
                if (httpConnection != null)
                    httpConnection.close();

            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return bitmp;
    }
}

不知道我哪里错了。请允许任何budy帮助我。

3 个答案:

答案 0 :(得分:3)

您的代码有几个问题:

  • BitmapLazyLoader类看起来像消费者。它包含一个Thread引用。仅此一点非常令人困惑,因为Runnables旨在传递给Thread构造函数,但Runnables不应该为了封装而知道线程。让这个分开,这个类只尝试生成一个线程,但是当你每次绘制一行时创建一个Runnable实例时,你最终会产生相当多的线程。这可能会在TooManyThreadsException被抛出,因为在BlackBerry中,最大线程数限制为每个应用程序16个。即使你没有达到极限,性能也会降低,因为运行单核CPU的黑莓手机不应该同时运行超过2-3个线程。即使你可以产生无限的线程,在BlackBerry你只能同时打开X连接(我认为整个操作系统的X是5,不确定这个)。 首先修改代码以确保只有一个工作线程正在下载图像。(如果可能的话,提取线程实例化并从Runnable类中启动)。
  • 下载位图时,您没有对其执行任何操作。查看ImageDownloadCompleted方法,它是空的。 (顺便说一下,方法的惯例是以小写字母开头)所以你应该将位图存储在某处并在列表中调用invalidate ,这样就会绘制存储的位图。

希望它有所帮助。

答案 1 :(得分:2)

我之前已经解决了这个问题,我在这里发布了我的技术,虽然它不是理想的解决方案,因为它与Screen类非常相似,但仍然可能有用。

屏幕类中的第一个数据库有一个数组,其大小等于列表字段项。

public class TempScreen extends MainScreen{
    Bitmap[] images=null;
    String[] urls={"image1_url", "image2_url".....};
    public TempScreen()
    {

        images=new Bitmap[urls.length];

    }

现在在ListFieldCallBack的drawListRow方法中,检查以下内容:

 public void drawListRow(ListField list, Graphics g, int index, int y, int width){
     if(bitmap[index]==null)
     {
         //Load placeholder image
     }
     else
         //Load Bitmap    
 }

现在创建一个线程类来下载图像:

public class ImageDownloader implements Runnable
{
    public void run()
    { 
        for(int i=0; i<size;i++)
        { 
             if(images[i]==null) 
             { 
                  images[i]=downloadImage(url[i]);//replace downloadImage method to whatever method       you have to download the bitmap from url 
                  UiApplication.getUiApplication().invokeLater(new Runnable(){
                      public void run()
                      {
                          list.invalidate()
                      }
                  });
              }
         }
    }
}

现在在屏幕类的构造函数中,在设置回调到listfield之后,启动线程:

Thread downloader=new Thread(new ImageDownloader());
downloader.start();

编辑:将TempScreen构造函数更改为以下内容:

public TempScreen()
    {

        images=new Bitmap[urls.length];
        size = urls.length;
        mylist = new ListField();
        mylist.setCallback(this);
        mylist.setSize(4);
        mylist.setRowHeight(getFont().getHeight() * 3);
        add(mylist);
        Thread downloader=new Thread(new ImageDownloader());
        downloader.start();
    }

答案 2 :(得分:2)

您可以尝试使用此链接: http://www.coderholic.com/blackberry-webbitmapfield/

您必须按照上面链接中的建议创建一个名为WebBitmapField的单独类。

如何在列表字段图像对象中使用该类:

  • 为每个图片网址创建WebBitmapField对象
  • photoList_vector是填充元素的向量 列表字段

    WebBitmapField web = new WebBitmapField("http://www.image1.png"); 
    
    photoList_vector.addElement(web);
    
    web = new WebBitmapField("http://www.image2.png"); 
    
    photoList_vector.addElement(web);
    

现在使用此向量处理列表字段......

在上面的行中,我们尝试确保当我们同时发送多个请求以获取图像时,每个图像对应一个特定的WebBitmapField对象。

然后将每个对象添加到矢量中,以便将其添加到列表字段中。

每个网址发送都绑定到WebBitmapField的对象。

因此,虽然请求是在一个单独的线程中发送的,但它只与其关联的对象绑定

希望它有所帮助 :)