【问题标题】:Reading from socket inputstreams causing android UI to freeze从套接字输入流读取导致 android UI 冻结
【发布时间】:2012-03-20 13:23:14
【问题描述】:

我正在尝试编写这个程序,它会根据变量的当前状态进行自我更新。我打算如何工作是通过定时任务不断将字符串“update”发送到服务器。服务器将识别该字符串并在 android 设备上发送变量的必要值。但是,我面临一些问题。字符串“update”正在发送而没有错误,但是当从服务器发回相应的值时,程序似乎无法读取回复。代码如下:

            //Open socket and initialize data streams
    try {
        socket = new Socket(serverIpAddress, applicationport);
        //in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
        //in = new DataInputStream(socket.getInputStream());
        out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(
                socket.getOutputStream())), true);
    } catch (UnknownHostException ex) {
        // TODO Auto-generated catch block
        ex.printStackTrace();
        ShowDialog("Login Error" + ex.getMessage());
    } catch (IOException ex) {
        // TODO Auto-generated catch block
        ex.printStackTrace();
        ShowDialog("Login Error" + ex.getMessage());
    }

    //Create new daemon timer
    updateData = new Timer(true);
    updateData.scheduleAtFixedRate(new TimerTask() {
        @Override
        public void run() {
            out.println("update");
            UpdateMethod();
            }//run
        }, 1000, 10000);//schedule the delays start/interval here



};

private void UpdateMethod() {
    //This method is called directly by the timer
    //and runs in the same thread as the timer.
    //It calls the method that will work with the UI
    //through the runOnUiThread method.
    this.runOnUiThread(Timer_Tick);
};//timermethod

private Runnable Timer_Tick = new Runnable() {
    public void run() {
        try {
            //in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            //String getx1 = null;
            //getx1 = in.readLine();
            //if (getx1 != null) {
                //float updatex1 = Float.parseFloat(getx1);
                //get_x1 = getx1;
                //}
            in = new DataInputStream(socket.getInputStream());
            /*try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }*/
            x1display = (TextView) findViewById(R.id.x1display);
            x1display.setText(in.readUTF());

        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        finally {
            if (in != null){
                try {
                    in.close();
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        }
    }
};

如您所见,我也尝试过使用 DataInputStream 和 BufferedReader,但无济于事。

编辑:似乎尝试从输入流中读取导致我的 UI 冻结。我不知道出了什么问题,因为我的代码似乎没有错误..

任何帮助或建议将不胜感激!

谢谢!

【问题讨论】:

  • 你试过用:InputStream is = socket.getInputStream();
  • 嗨哈克姆,你能更详细地解释一下我如何实现这个吗?谢谢
  • 我的意思是你替换 = new DataInputStream(socket.getInputStream());与 InputStream 是 = socket.getInputStream();因为我让它使用输入流工作

标签: java android sockets timer inputstream


【解决方案1】:

代码对我来说看起来不错。但它不起作用,所以看起来你需要把它切碎。

  • 测试套接字是否在没有定时器的情况下工作。建立一个套接字连接并在没有计时器和 UI 代码的情况下读取其响应

  • 如果可行,请引入 Timer 而不是 UI 代码

  • 如果可行,请执行整个操作(现在失败了)

在这个测试过程中的某个地方你应该能够找到罪魁祸首

【讨论】:

  • 您好 openmobster,在发布到 stackoverflow 之前,我曾尝试以这种方式对其进行故障排除。套接字工作正常,定时器工作正常,我的服务器定期接收“更新”字符串,但由于某种奇怪的原因,我无法触摸任何其他按钮或接收 android 客户端上的服务器输入.触摸任何按钮都会导致应用崩溃。
  • 某些东西正在冻结您的 UI 并崩溃,使其看起来像是您的按钮正在崩溃。查看代码,可能是 TimerTick 下的这一行可能会在等待来自套接字的输入时被冻结:x1display.setText(in.readUTF());这在 UI 线程上执行。也许尝试读取计时器任务中的输入流并将值作为参数提供给 UpdateMethod
  • 嗨 openmobster,看来你是对的。我已经将罪魁祸首缩小到读取输入流导致我的应用程序崩溃的原因。但是我不知道如何修复它,因为我的代码看起来合乎逻辑且正确。这绝对让我发疯。 :(
  • 确保服务器实际上正在回写一些东西。我知道你提到更新成功了。但是是服务器正在写入的套接字。只是预感
【解决方案2】:

正如您已经说过的,阅读会阻塞线程。您不应该在 UI 线程中阅读任何内容!此外,我没记错,在关闭输出之前关闭输入会做一些讨厌的事情。我建议关闭套接字并将 BufferedReader 放回原处。它应该是这样的:

//Open socket and initialize data streams
try {
    socket = new Socket(serverIpAddress, applicationport);
    in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
    out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(
            socket.getOutputStream())), true);
} catch (UnknownHostException ex) {
    ex.printStackTrace();
    ShowDialog("Login Error" + ex.getMessage());
} catch (IOException ex) {
    ex.printStackTrace();
    ShowDialog("Login Error" + ex.getMessage());
}

//Create new daemon timer
updateData = new Timer(true);
updateData.scheduleAtFixedRate(new TimerTask() {
    @Override
    public void run() {
        out.println("update");
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                try {
                    x1display = (TextView) findViewById(R.id.x1display);
                    x1display.setText(in.readUTF());
                } catch (IOException e) {
                    e.printStackTrace();
                }
            });
        try {
            socket.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }}, 1000, 10000);//schedule the delays start/interval here

顺便说一句,不要使用 printStackTrace():Why is exception.printStackTrace() considered bad practice?

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-31
    • 2016-02-11
    • 2015-03-21
    相关资源
    最近更新 更多