【问题标题】:Android AsyncTask stuckAndroid AsyncTask 卡住了
【发布时间】:2013-12-26 14:37:20
【问题描述】:

背景: android 应用程序的以下 AsyncTask 从服务器发送和接收所谓的请求对象。 如果用户对应用程序中的内容进行更改,则会生成新的请求对象并将其添加到同步队列中。如果他随后点击同步按钮,AsyncTask 将被创建并以他的请求作为参数执行。

处理程序最终获取所有答案并在数据库中设置必要的结果。然后,他最终通过调用 UI 线程 (onPostExecute) 上的一个方法来更新 UI。

public class RequestSender extends AsyncTask<Request, Void, Boolean>{

// Server data
private String host;
private int port = 1337;

private Socket socket;
private AnswerHandler handler;

public RequestSender(AnswerHandler handler) {
    this.host = "hostNameHere";
    this.handler = handler;
}

/**
 * This method gets started as asynchronous task when you call .run()
 * @return 
 */
@Override
protected Boolean doInBackground(Request... requests) {
    return sendAndReceive(requests);
}

private boolean sendAndReceive(Request... requests) {
    boolean isConnected = this.initSocket();
    if(isConnected) {
        this.send(requests);
        this.waitForAnswer();
    } else {
        handler.setRequests(requests);
    }
    return isConnected;
}

/**
 * Tries to open a socket on the android device to a specified Host
 */
private boolean initSocket() {
    try {
        SocketAddress sockaddr = new InetSocketAddress(host, port);
        socket = new Socket();
        socket.connect(sockaddr, 5000);
        return true;
    } catch (UnknownHostException e) {
        System.err.println("Unknown Host in initSocket()");
    } catch (IOException e) {
        System.err.println("Connection timed out");
    }
    return false;
}

/**
 * Tries to send a request to the server
 * @param request
 */

public void send(Request... request) {
    if(socket != null) {
        try {
            ObjectOutputStream out = new ObjectOutputStream(socket.getOutputStream());
            out.writeObject(request);
            out.flush();
        } catch (IOException e) {
            System.err.println("Couldn't write to socket in RequestSender");
        }
    }
}

/**
 * Waits for the answer from the server and reports the result in the handler
 */
private void waitForAnswer() {
    try {
        socket.setSoTimeout(5000);
        ObjectInputStream in = new ObjectInputStream(socket.getInputStream());
        Request[] answers = (Request[]) in.readObject();
        socket.close();
        handler.setRequests(answers);
    } catch (StreamCorruptedException e) {
        System.err.println("Failed to open stream from server");
    } catch (IOException e) {
        System.err.println("Failed to read answers from server");
    } catch (ClassNotFoundException e) {
        System.err.println("Failed to read class from server");
    }
}

@Override
protected void onPostExecute(Boolean a) {
    handler.updateUI();
}

}

现在我的问题: 整个事情几次都没有任何问题(这取决于我手机的善意多少次),但似乎任务卡在某个地方而没有在 System.err 上给我任何错误消息。 重新启动应用程序解决了问题,它再次运行没有任何问题。

我已经读到自 Honeycomb 以来,AsyncTasks 在一个线程上执行。我在打开的套接字上设置了一个超时并读入,所以一个卡住的任务应该在这个超时后终止。

我的代码有什么问题吗?您能想出一个解决方案吗?

【问题讨论】:

    标签: java android android-asynctask


    【解决方案1】:

    最近遇到这个问题,经过大量的调试和一周的头脑风暴,我终于得到了这个错误。

    好吧,让我们做一些功课。

    发送/接收数据的过程

    1. 建立连接。假设connectToServer() 是一个将设备物理连接到服务器的函数。
    2. 套接字/TCP 部分。在您的情况下,您有 doInbackground(),您在其中调用 initSocket() 来启动套接字连接。

    现实世界场景中,当您请求连接到服务器时需要一些时间,可能是一两秒。因此,您应该等待这段时间,然后再发起套接字连接请求。如果套接字请求在连接之前发送,那么它将进入锁定状态并在默认超时完成后释放,使其卡住

    编程场景

    connectToServer();
    
    // wait for 1 or 2 second.
    
    initSocket();   
    

    示例代码

        /* Function to check whether we are physically connected to the server or not */
    private boolean isConnEstablished(){
        WifiInfo connInfo = mManager.getConnectionInfo();
        return mManager.isWifiEnabled() && connInfo.getNetworkId() != -1 && connInfo.getIpAddress() != 0;
    }
    
    private void initSocket() {
        boolean scanning = true;
        int tryCount = 5; // we trying for 5 times
    
        try {
            while (scanning && tryCount > 0) {
                try {
                    if (isConnEstablished()) {
                        try{
                            Thread.sleep(500);
                        }catch (InterruptedException e){
                            Log.e("Yo", "sleep-error");
                        }
                        tConnection = new Socket(host, port);
                        scanning = false;
                        Log.e(getClass().getName(), "Socket connection established");
                    }else {
                        throw new ConnectException();
                    }
                } catch (ConnectException e) {
                    Log.e(getClass().getName(), "connecting again...");
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException ex) {
                        Log.e(getClass().getName(), "System sleep-error: " + ex.getMessage());
                    }
                }
               tryCount--;
            }
    
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-10-22
      • 1970-01-01
      • 2021-01-30
      • 1970-01-01
      • 2021-03-19
      • 1970-01-01
      • 1970-01-01
      • 2017-01-11
      相关资源
      最近更新 更多