2011-09-13 1 views
0

こんにちは、私は、私は画像をダウンロードし、画面上でレンダリングする必要があるボタンを持っているサンプルを試しています。私はそれを行うには、次のコードを使用しています。私は本当に間違っているどこかを知らない。それは私に違法を投げる例外。誰でも私のコードを見て、私に助けてください。nonuiスレッドからフィールドを追加すると、ブラックベリーで例外がスローされますか?

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

注:画像のダウンロードは正常です。私は他のサンプルでもテストしました。

私は次のコードを変更し、ダウンロードロジックを別のスレッドに分けました。

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

答えて

4

正確にどのような例外がありますか(メッセージはありますか)?あなたが違法な行為をするかもしれない場合Bitmapが大きすぎてBitmapFieldインスタンスを作成できない場合は、 Bitmapの寸法(幅x高さ)はどのくらいですか? 〜1.5 Mpxからの経験では、BitmapField(正確な制限はデバイスモデル/ OSレベルによって異なります)を作成することはできません。

UPDATE:

OK、その後、何が起こっているかを把握するためには、次のアプローチを試みることができますか?

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セクションに残してください)。

+0

例外はイメージサイズまたはメモリの制約によるものではありません。それは、ネットワークスレッドから、UIにフィールドを追加している間です。 –

+0

@Neel:UPDATEセクションを参照 –

+0

Arhimed ..ありがとう。今働いている。 –

1

のようなスレッドを呼び出します(イベントロックをキャプチャせずに)UIスレッドの更新UIを呼び出すスレッドが完了した後

+0

私はthreadを拡張した内部クラスを取り、次に私のfieldChanged()からrunメソッドを呼び出しました。ここでも問題は同じです。私はそれがイメージをダウンロードしているが、私はまだuiで更新するための問題があることを願っています。 –

+0

スタックトレースを投稿できますか? – Dan

1

いくつかのこと...

1)Downloadは、内部クラスがあるので、あなたはので、以下にごupdateUI方法を変更activeScreenへの参照を必要としません:

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)あなたはどのようなタイプの画像をダウンロードしていますか?あなたは、MDSを使用していない場合は、シミュレータでは

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

4):等のJPGのみ、PNG画像を処理するには、代わりにBitmapクラスの静的メソッドのバイト配列を処理するために、このようなものが必要URLに接尾辞を付ける必要があります;deviceside=true

私のために働きます。例外なく。 OS 5 9550シミュレータで動作します。

関連する問題