2

我是 BlackBerry 开发的新手。但对安卓很好。

我想在 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;
    }
}

不知道我哪里错了。请任何朋友都可以帮助我。

4

3 回答 3

3

您的代码有几个问题:

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

希望能帮助到你。

于 2012-12-13T12:00:49.700 回答
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()
                      }
                  });
              }
         }
    }
}

现在在屏幕类的构造函数中,将回调设置为列表字段后,启动线程:

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();
    }
于 2012-12-13T13:08:32.773 回答
2

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

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

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

  • 为每个图像 url 创建 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 对象。

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

每个 url 发送都绑定到 WebBitmapField 的一个对象。

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

希望能帮助到你 :)

于 2012-12-18T06:16:36.443 回答