从nonui线程添加字段会在黑莓中引发异常?

时间:2011-09-13 13:50:46

标签: blackberry

大家好我正在尝试一个样本,我有一个按钮,下载图像,然后它需要在屏幕上呈现。我使用以下代码来完成它。不知道某个地方我真的错了。它抛出我非法的例外。任何人都可以看看我的代码并给我一些帮助。

import java.io.IOException;
import java.io.InputStream;
import javax.microedition.io.Connector;
import javax.microedition.io.HttpConnection;
import net.rim.device.api.system.Application;
import net.rim.device.api.system.Bitmap;
import net.rim.device.api.ui.Field;
import net.rim.device.api.ui.FieldChangeListener;
import net.rim.device.api.ui.UiApplication;
import net.rim.device.api.ui.component.BitmapField;
import net.rim.device.api.ui.component.ButtonField;
import net.rim.device.api.ui.container.MainScreen;


public class GoogleChart extends MainScreen implements FieldChangeListener{

    ButtonField btn = new ButtonField("Download");

    GoogleChart activeScreen = null;

    public GoogleChart() {
        setTitle("Download image"); 

        btn.setChangeListener(this);
        add(btn);

        this.activeScreen = (GoogleChart)UiApplication.getUiApplication().getActiveScreen();
    }

    public void fieldChanged(Field field, int context) {
        if(field == btn){
            updateUI();
        }
    }

    private void updateUI(){
        synchronized (Application.getEventLock()) {
            activeScreen.add(new BitmapField(downloadImage()));
            activeScreen.invalidate();
        }   
    }
    public Bitmap downloadImage() {
        byte[] dataArray;
        InputStream input;

        StringBuffer url = new StringBuffer("IMAGE URL"); 

        HttpConnection httpConn = null;
        Bitmap googleImage = null;
        try {
            httpConn = (HttpConnection) Connector.open(url.toString());

            input = httpConn.openInputStream();

            dataArray = net.rim.device.api.io.IOUtilities.streamToBytes(input);

            googleImage = Bitmap.createBitmapFromBytes(dataArray, 0, -1, 1);

        } catch (IOException e) {
            e.printStackTrace();
        }
            return googleImage;
    }
}

注意:图像下载工作正常。即使我已经测试过其他样品。

根据Dan的建议,我更改了以下代码,并将下载逻辑分成另一个线程。

class Download extends Thread{
    Bitmap googleImage = null;

    private void updateUI(){
        synchronized (Application.getEventLock()) {
            if(googleImage != null){                
            activeScreen.add(new BitmapField(googleImage));
            activeScreen.invalidate();
            }
        }   
    }

    public void run() {
        googleImage = downloadImage();
        updateUI();

    }

    public Bitmap downloadImage() {
        byte[] dataArray;
        InputStream input;

        StringBuffer url = new StringBuffer("http://"); 

        HttpConnection httpConn = null;
        Bitmap googleImage = null;
        try {
            httpConn = (HttpConnection) Connector.open(url.toString());

            input = httpConn.openInputStream();

            dataArray = net.rim.device.api.io.IOUtilities.streamToBytes(input);

            googleImage = Bitmap.createBitmapFromBytes(dataArray, 0, -1, 1);

        } catch (IOException e) {
            e.printStackTrace();
        }
            return googleImage;
    }
}

并像这样调用线程

public void fieldChanged(Field field, int context) {
        if(field == btn){
            new Download().start();
        }
    }

3 个答案:

答案 0 :(得分:4)

你到底有什么例外(它有没有消息?)?在什么步骤/线?作为一种可能的情况,如果Bitmap太大而无法创建BitmapField实例,则可能会收到非法异常。您的Bitmap有哪些尺寸(宽x高)?根据我从~1.5 Mpx开始的经验,无法创建BitmapField(确切的限制取决于设备型号/操作系统级别)。

<强>更新

好的,然后找出发生了什么可以尝试以下方法吗?

private void updateUI() {
    UiApplication.getUiApplication().invokeLater(new Runnable() {
        public void run() {
            if (googleImage == null) {
                Dialog.alert("googleImage is null");
            } else {
                Dialog.alert("googleImage is not null");
                try {
                    BitmapField b = new BitmapField(googleImage);
                    Dialog.alert("BitmapField has been created OK");
                    activeScreen.add(b);
                    Dialog.alert("BitmapField has been added OK");
                    // no need to invalidate, since adding a new Field forces
                    // the screen to be repainted
                } catch (Exception e) {
                    Dialog.alert("Got error: " + e);
                }
            }
        }
    });
}

你看到了什么消息?如果你已经“添加了BitmapField”,那么只需删除所有警报(只留在catch部分 - 以防万一),它应该可以正常工作。

答案 1 :(得分:1)

您正在捕获事件锁定并执行下载(锁定整个应用程序直到完成。 您需要使用一个线程来执行UI线程的下载(不捕获事件锁定)并在线程完成其任务后调用您的更新UI

答案 2 :(得分:1)

一些事情......

1)由于Download是内部类,因此您不需要引用activeScreen因此,请将updateUI方法更改为以下内容:

private void updateUI() {
        synchronized (Application.getEventLock()) {
            if(googleImage != null ) {   
            add(new BitmapField(googleImage));
            //invalidate();
        }   
    }

2)FieldChangeListener对我不起作用。如果您使用new ButtonField("blah", ButtonField.CONSUME_CLICK)之类的实例进行实例化,则可能会有效。但是,我正在使用以下内容收听点击:

ButtonField btn = new ButtonField("Download") {
    protected boolean navigationClick(int arg0, int arg1) {
        new Download().start();
        return true;
    }
};

3)你下载什么类型的图像?要处理JPG,PNG等,你需要这样的东西来处理Bitmap类上的字节数组而不是静态方法:

EncodedImage img = EncodedImage.createEncodedImage(dataArray, 0, dataArray.length);
googleImage = img.getBitmap();

4)在模拟器中,如果您没有使用MDS,则需要使用;deviceside=true

后缀网址

适合我。没有例外。在OS 5 9550模拟器上运行。