我是黑莓开发的新手,我正在创建一个原生的黑莓应用程序。在我的应用程序的每个屏幕上,我需要在同一连接上向服务器发送和接收数据。
到目前为止我所做的是我已经创建了一个ConnectToServer
类,它有一堆发送和接收方法。我在主屏幕上实例化它,并将其作为参数传递给每个屏幕。
该类不是线程,因为我只在用户输入信息并按下按钮时才能读写。所以基本上我在事件线程上使用inputStream和outputStream,我听说是 BAD 。然后我问ConnectToServer
让我知道服务器发送了什么。例如,我得到一个用于制作ListField的向量。
如何进行这些UI更新?
public class Screen3 extends MainScreen {
ConnectToServer con;
Vector v;
public Screen3(String exerciseName, ConnectToServer connect)
{
con = connect;
con.send(exerciseName);
v = con.receiveVector();
mylist = new listField();
mylist.setSize(v.size());
add(mylist);
}
public void drawListRow(...)
{
graphics.drawText((String) v.elementAt(index)
}
}
答案 0 :(得分:0)
所以,有很多方法可以解决这个问题。首先,由于您似乎只需要ConnectToServer
的一个实例,并且您当前不得不传递它,您可以尝试将该类设为Singleton object。这不是必需的,与线程问题没有任何关系,但我只提供它作为解决方案,适用于您希望强制执行只有一个事物的例子,并希望避免在任何地方传递它。一个简单的Singleton实现可能是这样的:
public class ConnectToServer {
private static ConnectToServer _instance;
/** use this static method to get the one and only instance */
public static ConnectToServer getInstance() {
if (_instance == null) {
_instance = new ConnectToServer();
}
return _instance;
}
/** private to enforce Singleton pattern */
private ConnectToServer() {
}
}
并在屏幕上使用它(不需要再将其传递给构造函数):
ConnectoToServer connection = ConnectToServer.getInstance();
connection.blahBlahBlah();
现在,关于线程问题。你是对的,你不应该在主(也就是“UI”,又名“事件”)线程上执行网络请求。如果您有一个不错的单独ConnectToServer
类,则可以更轻松地封装此行为。不是使用同步 send()
和receiveVector()
方法的UI客户端,而是创建一个只启动请求的方法,以及ConnectToServer
类将使用的另一个回调方法响应回来时打电话。 ConnectToServer
类将使用Thread
来执行此工作,从而避免在请求期间冻结UI。
我将定义UI客户端将实现的interface
:
public interface RequestListener {
/** listeners must implement this method to get data. method will be called on the UI thread */
void onDataReceived(Vector response);
}
然后是新的(部分)ConnectToServer
类:
public class ConnectToServer {
private Thread _worker;
private RequestListener _listener;
public void setRequestListener(RequestListener listener) {
// note: this implementation only allows one listener at once.
// make it a list if you need something more
_listener = listener;
}
/** initiate a network request on a background thread */
public void sendRequest(final String request) {
_worker = new Thread(new Runnable() {
public void run() { // run on the background/worker thread
send(request);
final Vector response = receiveVector();
if (_listener != null) {
// this assumes all our listeners are UI objects, so we pass
// data back to them on the UI thread:
UiApplication.getUiApplication().invokeLater(new Runnable() {
public void run() { // run on UI thread
_listener.onDataReceived(response);
}
});
}
}
});
_worker.start();
}
}
请注意,您还应在此课程send()
中制作原始 receiveVector()
和private
方法。它们现在只能从内部类中调用,而不是直接从UI客户端调用。
然后,您需要像这样编写Screen
类:
public class Screen3 extends MainScreen implements RequestListener {
public Screen3(String exerciseName) {
ConnectToServer connection = ConnectToServer.getInstance();
connection.setRequestListener(this);
// kick off the request (on a background thread)
connection.sendRequest(exerciseName);
}
public void onDataReceived(Vector response) {
if (mylist == null) {
// first time data has been received, so create and add the list field:
mylist = new listField();
add(mylist);
}
mylist.setSize(response.size());
// TODO: presumably, you would copy the contents of 'response' into 'mylist' here
}
}
此外,您可能还希望对服务器类进行编码,以防止多个UI客户端发出并发请求,允许取消当前请求等。但是上面的内容应该让您开始使用解决方案它提供了一个响应式应用程序,而不会冻结您的UI。