我正在使用ListField Control来显示从xml webservice返回的数据。我想每分钟刷新ListField或屏幕,以使用新记录或数据更新ListField。
我尝试使用下面的代码,但它无法正常工作(它挂起)。
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);
}
ResponseHandler handler = new ResponseHandler();
ListField listUsers = new ListField(handler.getItem().size());
public MyScreen() {
setTitle("yQAforum");
//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.");
}
//Return vector sze from the handler class
listUsers.setSize(handler.getItem().size());
listUsers.setCallback(this);
listUsers.setEmptyString("No Users found", 0);
add(listUsers);
}
答案 0 :(得分:2)
您正在尝试从UI线程上的Web服务获取数据。这几乎总是错误的。
UI线程(也称为主线程)负责绘制UI,跟踪用户操作,如触摸或通过触控板/轨迹球导航。如果阻止UI线程等待远程Web服务器响应,则它无法为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());
}
已经在UI线程上调用MyApp()
构造函数,因此无需使用invokeLater()
在UI线程上执行pushScreen()
调用。如果在MyApp
构造函数中运行,它已经在UI线程上调用。此外,5000毫秒的延迟并没有多大帮助。这只会将您的应用启动延迟5秒,用户会讨厌。
如果您尝试实施启动画面或其他类似功能,当应用启动时,请搜索堆栈溢出“BlackBerry启动画面”,我相信您会找到结果。
现在,一旦创建了MyScreen
类,您应该注意而不是从UI线程获取Web服务结果。 MyScreen
构造函数将在UI线程上运行。如果需要,您可以在显示屏幕后在后台线程上启动 Web服务请求。一种方法是使用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
}
});
}
}
如果网络服务没有响应,或者需要花费超过一分钟的时间,您需要添加一些错误处理(如果最后一个尚未完成,您将不希望发出新请求)。
但是,这应该让你开始。
注意:一旦解决了在UI线程上运行网络代码的问题,您可能仍然发现您的代码无效。获取Web服务数据可能会出现问题。你必须调试它。我只向您展示发布的代码一个问题。如果您仍然遇到Web服务提取问题,请发布另一个问题(修复了UI线程问题)。感谢。