Обновление пользовательского интерфейса Android с использованием потоков

android user-interface

65194 просмотра

5 ответа

Я пишу приложение для Android-чата. Я прослушиваю соединения, получаю данные и вижу их в Log.d, но всякий раз, когда я пытаюсь обновить свой пользовательский интерфейс, происходит сбой приложения.

Фрагмент кода:

private class chatReceiver implements Runnable {
    @Override
    public void run() {
        try {
            skt = new DatagramSocket(Integer.parseInt(Main.prefs.getString("port_number", "5432")));
            DatagramPacket rcvPkt = new DatagramPacket(rcvBuf,rcvBuf.length);
            String ack = "Hello from our SimpleUDPServer";
            byte[] sndBuf = ack.getBytes();
            while (true) {
                Log.d("Server received: " ,"entered loop");
                skt.receive(rcvPkt);
                String rcvMsg = new String(rcvBuf, 0, rcvPkt.getLength(), "UTF-8");
                Log.d("Server received: " ,"receiving" + rcvMsg);
                if (rcvMsg != null) {
                    Log.d("Server received: " ,"not equal null");
                    // I want to update my UI here
                }
                DatagramPacket k = new DatagramPacket(sndBuf, sndBuf.length,
                        rcvPkt.getAddress(), rcvPkt.getPort());
                skt.send(k);
                Log.d("Server sent" ,ack);

            }
        } catch (IOException ex) {
            Log.d("ThreadStart", "Error Starting thread" + ex.getStackTrace());
        }

    }
} 

и чтобы обновить пользовательский интерфейс, который я использую:

public static void updateUI(Bubble b, View itemView) {

    TextView txt_display_name = (TextView) itemView
            .findViewById(R.id.display_name);
    txt_display_name.setText(b.getDisplay_name());
    TextView txt_chat_body = (TextView) itemView
            .findViewById(R.id.chat_body);
    txt_chat_body.setText(b.getChat_body());
    TextView txt_creation_date = (TextView) itemView
            .findViewById(R.id.creation_date);
    txt_creation_date.setText(b.getCreation_time());
}

Приложение продолжает падать.

Автор: AhmadAssaf Источник Размещён: 12.11.2019 09:37

Ответы (5)


58 плюса

Решение

Вы не можете ничего коснуться в потоке пользовательского интерфейса из фонового потока , чтобы сделать это Handlers, инициализируйте свой фон, threadпередав ему Handlerобъект. Когда поступают данные, используйте handlerдля отправки сообщения в пользовательский интерфейс. В пользовательском интерфейсе, когда threadприходит сообщение из фона , просто обновите Views.

Пример кода

в фоновом потоке:

if(dataArrives){
    Message msg = handler.obtainMessage();
    msg.what = UPDATE_IMAGE;
    msg.obj = bitmap;
    msg.arg1 = index;
    handler.sendMessage(msg);
}

в потоке пользовательского интерфейса:

final Handler handler = new Handler(){
  @Override
  public void handleMessage(Message msg) {
    if(msg.what==UPDATE_IMAGE){
      images.get(msg.arg1).setImageBitmap((Bitmap) msg.obj);
    }
    super.handleMessage(msg);
  }
};

и передать handlerна задний план thread.

Автор: Franco Размещён: 03.03.2011 06:54

71 плюса

Вы не можете изменять элементы пользовательского интерфейса из не-пользовательского потока. Попробуйте использовать runOnUiThread .

runOnUiThread(new Runnable(){
    @Override
    public void run(){
        // change UI elements here
    }
});
Автор: user634618 Размещён: 03.03.2011 06:53

8 плюса

Или просто используйте AsyncTask , это более полезно IMHO.

Автор: Olsavage Размещён: 03.03.2011 08:17

0 плюса

Используйте этот метод для обновления вашего пользовательского интерфейса из рабочего потока, здесь это хорошо объяснено.

Примечание: - Если вы используете, progressbar.setProgress(progress)вы можете обновить непосредственно с рабочего, threadпотому что метод ProgressBarвнутреннего вызова setProgress()использует Handler.

Автор: Bijay Размещён: 17.02.2017 09:29

-1 плюса

private void yourMethodName(){

new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                //do some heavy task here on main separate thread like: Saving files in directory, any server operation or any heavy task

                 ///Once this task done and if you want to update UI the you can update UI operation on runOnUiThread method like this:

                         homeActivity.runOnUiThread(new Runnable() {
                            @Override
                            public void run() {
                                txtview.setText("some value");
                                edittext.setText("some new value");
                            }
                        });
                }
                catch (Exception e) {
                  //print the error here
                }
            }
        }).start();
}
Автор: Nikunjkumar Kapupara Размещён: 01.11.2017 05:43
Вопросы из категории :
32x32