所以,有很多方法可以解决这个问题。首先,由于您似乎只想要一个 的实例ConnectToServer
,而您目前不得不传递它,您可以尝试将该类设为Singleton 对象。这不是必需的,并且与您的线程问题没有任何关系,但我仅将它作为一种解决方案提供,用于您想要强制只有一个实例的情况,并希望避免传递它到处。一个简单的 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
将使用 aThread
来执行这项工作,从而避免在请求期间冻结 UI。
我将定义interface
UI 客户端将实现的:
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()
和方法。现在只能从类内部调用它们,而不是直接从 UI 客户端调用。receiveVector()
private
然后,您需要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 .