Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/blackberry/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
从非UI线程添加字段会在blackberry中引发异常?_Blackberry - Fatal编程技术网

从非UI线程添加字段会在blackberry中引发异常?

从非UI线程添加字段会在blackberry中引发异常?,blackberry,Blackberry,大家好,我正在尝试一个例子,我有一个按钮,下载一个图像,然后它需要在屏幕上渲染。我使用下面的代码来完成它。我不知道我哪里出了问题。它向我抛出非法异常。任何人都可以看看我的代码,并为我提供一些帮助 import java.io.IOException; import java.io.InputStream; import javax.microedition.io.Connector; import javax.microedition.io.HttpConnection; import net.

大家好,我正在尝试一个例子,我有一个按钮,下载一个图像,然后它需要在屏幕上渲染。我使用下面的代码来完成它。我不知道我哪里出了问题。它向我抛出非法异常。任何人都可以看看我的代码,并为我提供一些帮助

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();
        }
    }

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

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

您到底得到了什么异常(它有任何消息吗?)?在哪一步/哪一行?如果您的
位图
太大,无法创建
位图
实例,您可能会遇到非法异常。您的
位图
有哪些维度(宽度x高度)?根据我的经验,从~1.5 Mpx开始,就不可能创建
位图
(具体限制取决于设备型号/操作系统级别)

更新:

好的,那么为了弄清楚发生了什么,你可以尝试以下方法吗

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已添加OK”,那么只需删除所有警报(只需在
catch
部分保留“仅限”以防出现),它应该可以正常工作。

你到底得到了什么异常(它有任何消息吗?)?在哪一步/哪一行?如果您的
位图
太大,无法创建
位图
实例,您可能会遇到非法异常。您的
位图
有哪些维度(宽度x高度)?根据我的经验,从~1.5 Mpx开始,就不可能创建
位图
(具体限制取决于设备型号/操作系统级别)

更新:

好的,那么为了弄清楚发生了什么,你可以尝试以下方法吗

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已添加OK”,那么只需删除所有警报(只需在“捕获”部分保留“仅限”以防出现),它应该可以正常工作。

一些事情

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

private void updateUI() {
        synchronized (Application.getEventLock()) {
            if(googleImage != null ) {   
            add(new BitmapField(googleImage));
            //invalidate();
        }   
    }
ButtonField btn = new ButtonField("Download") {
    protected boolean navigationClick(int arg0, int arg1) {
        new Download().start();
        return true;
    }
};
2) FieldChangeListener不适用于我。如果您使用类似于
new ButtonField(“blah”,ButtonField.CONSUME_CLICK”)的东西进行实例化,它可能会工作。但是,我正在使用以下内容来侦听单击:

private void updateUI() {
        synchronized (Application.getEventLock()) {
            if(googleImage != null ) {   
            add(new BitmapField(googleImage));
            //invalidate();
        }   
    }
ButtonField btn = new ButtonField("Download") {
    protected boolean navigationClick(int arg0, int arg1) {
        new Download().start();
        return true;
    }
};
3) 您正在下载哪种类型的图像?要处理JPG、PNG等。您需要这样的内容来处理字节数组,而不是
位图
类上的静态方法:

EncodedImage img = EncodedImage.createEncodedImage(dataArray, 0, dataArray.length);
googleImage = img.getBitmap();
4) 在模拟器中,如果不使用MDS,则需要在URL后面加上
;deviceside=true

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

一些事情

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

private void updateUI() {
        synchronized (Application.getEventLock()) {
            if(googleImage != null ) {   
            add(new BitmapField(googleImage));
            //invalidate();
        }   
    }
ButtonField btn = new ButtonField("Download") {
    protected boolean navigationClick(int arg0, int arg1) {
        new Download().start();
        return true;
    }
};
2) FieldChangeListener不为我工作。如果您使用类似于
newbuttonfield(“blah”,ButtonField.CONSUME_CLICK)的东西进行实例化,
它可能会起作用。但是,我正在收听以下内容:

private void updateUI() {
        synchronized (Application.getEventLock()) {
            if(googleImage != null ) {   
            add(new BitmapField(googleImage));
            //invalidate();
        }   
    }
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,则需要在URL后面加上
;deviceside=true


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

我使用了一个扩展线程的内部类,然后从fieldChanged()调用了run方法。这里的问题仍然是一样的。我希望它正在下载图像,但仍然存在在ui中更新的问题。我使用了一个扩展线程的内部类,然后从fieldChanged()调用了run方法。这里的问题仍然是一样的。我希望它正在下载图像,但我仍然有在ui中更新的问题。异常不是由于图像大小或任何内存限制。这是在从网络线程向UI添加字段时发生的。异常不是由于图像大小或任何内存限制造成的。这是在从网络线程向UI添加字段时发生的。