UIスレッドでWebサービスからデータをフェッチしようとしています。それはほとんどの場合間違ったことです。
UIスレッド(メインスレッドとも呼ばれます)は、UIの描画、タッチなどのユーザーアクションの追跡、またはトラックパッド/トラックボールを介したナビゲーションを担当します。リモートWebサーバーが応答するのを待ってUIスレッドがブロックされている場合、UIを処理できません。
行う必要のある変更がいくつかあります。
public MyApp() {
// Push a screen onto the UI stack for rendering.
UiApplication.getUiApplication().invokeLater(new Runnable() {
public void run() {
UiApplication.getUiApplication().pushScreen(new MyScreen());
}
},5000,true);
}
に変更する必要があります
public MyApp() {
// Push a screen onto the UI stack for rendering.
pushScreen(new MyScreen());
}
コンストラクターはMyApp()
すでにUIスレッドで呼び出されているため、UIスレッドで呼び出しinvokeLater()
を実行するためにを使用する必要はありませんpushScreen()
。MyApp
コンストラクター内から実行した場合、UIスレッドで既に呼び出されます。また、5000ミリ秒の遅延はあまり役に立ちません。これにより、アプリの起動が5秒遅れるだけで、ユーザーはこれを嫌います。
スプラッシュ画面などを実装しようとしている場合は、アプリの起動時にスタックオーバーフローで「BlackBerryスプラッシュ画面」を検索してください。結果が見つかるはずです。
これで、クラスが作成されたら、UIスレッドからWebサービスの結果をフェッチしないMyScreen
ように注意する必要があります。コンストラクターはUIスレッドで実行されます。必要に応じて、画面が表示されたら、バックグラウンドスレッドでWebサービスリクエストを開始できます。そのための1つの方法は、次を使用することです。MyScreen
onUiEngineAttached()
protected void onUiEngineAttached(boolean attached) {
if (attached) {
// TODO: you might want to show some sort of animated
// progress UI here, so the user knows you are fetching data
Timer timer = new Timer();
// schedule the web service task to run every minute
timer.schedule(new WebServiceTask(), 0, 60*1000);
}
}
public MyScreen() {
setTitle("yQAforum");
listUsers.setEmptyString("No Users found", 0);
listUsers.setCallback(this);
add(listUsers);
}
private class WebServiceTask extends TimerTask {
public void run() {
//Fetch the xml from the web service
String wsReturnString = GlobalV.Fetch_Webservice("myDs");
//Parse returned xml
SAXParserImpl saxparser = new SAXParserImpl();
ByteArrayInputStream stream = new ByteArrayInputStream(wsReturnString.getBytes());
try {
saxparser.parse( stream, handler );
}
catch ( Exception e ) {
response.setText( "Unable to parse response.");
}
// now, update the UI back on the UI thread:
UiApplication.getUiApplication().invokeLater(new Runnable() {
public void run() {
// TODO: record the currently selected, or focused, row
//Return vector sze from the handler class
listUsers.setSize(handler.getItem().size());
// Note: if you don't see the list content update, you might need to call
// listUsers.invalidate();
// here to force a refresh. I can't remember if calling setSize() is enough.
// TODO: set the previously selected, or focused, row
}
});
}
}
Webサービスが応答しない場合、または1分以上かかる場合に備えて、エラー処理を追加する必要があります(最後のリクエストが終了していなければ、新しいリクエストを作成したくないでしょう)。
しかし、これで始められるはずです。
注: UIスレッドでネットワークコードを実行する際の問題を修正しても、コードが機能しない場合があります。Webサービスデータのフェッチで問題が発生する可能性があります。それをデバッグする必要があります。投稿されたコードに関する問題を1つだけ示しています。それでもWebサービスのフェッチに問題がある場合は、別の質問を投稿してください(UIスレッドの問題は修正されています)。ありがとう。