1

我正在创建一个与服务器上的数据库交互的 j2me 应用程序。因此我启动了一个线程来连接到服务器。我在一个单独的类中处理我的所有命令操作,该类实现CommandListener.

当我尝试获取服务器返回的响应时,我得到一个空字符串。我曾尝试等待连接到服务器的线程返回,但这会使应用程序无响应。

下面是我正在使用的代码。

//my network worker class.
public class NetworkConnector implements Runnable {
    //constructor
    public NetworkConnector(String url){
       //url =>server url to connect to.
       Thread thread = new Thread(this);
       thread.start();
    }

    private String serverReply="";
    private String url="

    //method to connect to the server and return the 
    //response from the server.
    public String sendData(String serverUrl) {

      //open streams to connect to the Server.
      httpConn = (HttpConnection)  
      Connector.open(serverUrl,Connector.READ_WRITE, true);
      httpConn.setRequestMethod(HttpConnection.GET);

      inStream = httpConn.openInputStream();
      int read;
      while ((read = inStream.read()) != -1) {
        sb.append((char) read);
      }

      return sb.toString();
   }


   public String getServerReply() {
     //serverReply is a class variable.
     return serverReply;
   }

   public void run(){
      //call the send method that connects to the server.
       serverResponse = sendData(Url);
   }

} //end of connector class.

// this class is where all my Command Actions are
//implemented. 
public class CommandActionController implements
CommandListener, DataReceiver {

public void commandAction(Command cmd, Displayable d) {
   //networkMgr => is the worker class that makes
   //connection to the server.
   networkMgr = new NetworkConnector("http://localhost
   /JsonPhp/login.php?uname=" + loginUserInfo.userName +
   "&passwd=" + loginUserInfo.password);

   //here am getting the response from the server.
   String serverResponse = networkMgr.getServerReply();

   //at this point the ServerReponse String is Empty =>
   //yet the server is supposed to return some String.
   System.out.println("xxxxxxxxxxxxxxxxxx
   ServerResponse =" + serverResponse);
   }

   }//end of CommandListener class.
4

3 回答 3

3

你对serverResponse价值的期望是错误的;当您尝试commandAction使用问题中的代码片段获取它时,它可能是空的。

为了获得非空值,您需要重新设计方法NetworkConnector.getServerReply()以使其正确等待线程完成并确实获得服务器响应。

但是,如果您这样做,您还必须重新设计CommandActionController以保持用户界面响应 - 您的“等待连接到服务器的线程”的测试表明了这一点。

重新设计的代码应该只是启动服务器连接线程并commandAction尽快退出(可能更改为一些“等待屏幕”让用户看到发生了什么)。只有在获得服务器响应后才能触发下一次屏幕更新。

考虑学习专门针对解释如何正确设计此类应用程序的教程 -网络、用户体验和线程

本文解释了 MIDlet 如何在不影响用户界面的情况下建立网络连接。它包括六个迭代示例,说明多线程网络和等待屏幕的使用...

于 2012-10-22T07:53:34.663 回答
0

如果没有 java.util.concurrent,我会这样做:

Result handleRequest(){
    final String url = // get url
    Work work = new Work(url):
    Thread t = new Thread(work);
    t.start();
    // do other stuff
    if(t.isAlive()){
        // still running
    }
    // this waits until the work is done
    // and it will be safe to access work.result after
    // this call has returned.
    t.join(); 
    return work.result;
}

进而

class Work implements Runnable{
    final String url;
    Result result;
    public void run(){
        this.result = // do your network stuff
    }
}
于 2012-10-22T12:58:22.617 回答
-2

您不应该在构造函数中启动线程。此外,runnable 旨在传递给线程。最简单(也是“正确”)的方法如下:

  1. 实施 aCallable而不是 a Runnable
  2. 使用 aExecutorService而不是 aThread
  3. 使用Future对象进行异步处理/响应用户

这是一个简单的例子。

class Stuff {
    final ExecutorService exec = 
                 Executors.newCachedExecutorService(// please see doc);
    Result process(String url){
        Future<Result> future = exec.submit(new Work(url));
        // do some other stuff
        if(future.isDone()){
            // return result?
        }
        return future.get(); // this call will wait until result is available
    }
} 

进而

class Work implements Callable<Result> {
    final String url;
    Result call() throws Exception {
        // do your network stuff here
        return result;
    }
}

java.util.concurrent.ExecutorService.submit()有关详细信息,请参阅java.util.concurrent.Future和的文档java.util.concurrent.Callable

于 2012-10-22T10:50:39.413 回答