Чтение из входных потоков сокетов, вызывающих зависание пользовательского интерфейса Android - PullRequest
0 голосов
/ 20 марта 2012

Я пытаюсь написать эту программу, которая обновляет себя в текущем состоянии переменной. Как я хотел, чтобы это работало, так это с помощью временной задачи постоянно посылать строку «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, но безрезультатно.

Edit: Кажется, что попытка чтения из входного потока вызывает зависание моего пользовательского интерфейса. Я понятия не имею, что не так, поскольку мой код, кажется, без ошибок ..

Любая помощь или совет будет принята с благодарностью!

Спасибо!

Ответы [ 2 ]

0 голосов
/ 08 ноября 2013

Как вы уже сказали, чтение блокирует поток. Вы никогда не должны читать что-то в потоке пользовательского интерфейса! Кроме того, насколько я помню, закрытие ввода перед закрытием вывода делает некоторые неприятные вещи. Я бы предложил вместо этого закрыть сокет и снова установить 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 (): Почему исключение.printStackTrace () считается плохой практикой?

0 голосов
/ 20 марта 2012

Код выглядит хорошо для меня.Но это не работает, так что похоже, что вам нужно нарезать его.

  • Проверьте, работает ли сокет без таймера.Установите соединение через сокет и прочитайте его ответ без таймера и кода пользовательского интерфейса

  • Если это работает, введите таймер, но не код пользовательского интерфейса

  • Если это работает, сделайте все это (что сейчас не работает)

Где-то в этом тестовом процессе вы сможете найти виновника

...