我是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帮助我。
答案 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的单独类。
如何在列表字段图像对象中使用该类:
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的对象。
因此,虽然请求是在一个单独的线程中发送的,但它只与其关联的对象绑定
希望它有所帮助 :)