使用线程更新Android UI

Ahm*_*saf 28 user-interface android

我正在写一个Android聊天应用程序.我正在监听连接,我收到数据,我可以看到它Log.d,但每当我尝试更新我的UI时,应用程序崩溃.

代码段:

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());
        }

    }
} 
Run Code Online (Sandbox Code Playgroud)

并更新我使用的UI:

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());
}
Run Code Online (Sandbox Code Playgroud)

应用程序不断崩溃.

use*_*618 72

您无法从非UI线程更改UI元素.尝试使用runOnUiThread.

runOnUiThread(new Runnable(){
    @Override
    public void run(){
        // change UI elements here
    }
});
Run Code Online (Sandbox Code Playgroud)

  • 使用 runOnUiThread 只能用于非常非常短的任务。如果任务花费的时间较长,那么用户将体验到应用程序冻结的情况。 (2认同)

Fra*_*nco 58

您无法从后台线程触摸UI线程中的任何内容,进行此操作Handlers,初始化您thread传递Handler对象的背景.当数据到达时使用它handler向UI发送消息.在UI中,当来自后台的消息thread到来时,只需更新即可Views.

示例代码段:

在后台线程中:

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

在UI线程中:

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);
  }
};
Run Code Online (Sandbox Code Playgroud)

并传递handler给背景thread.

  • @Franco -1省略了有关“将处理程序传递给后台线程”的部分,这似乎是最重要的部分 (2认同)

Ols*_*age 8

或者只是使用AsyncTask,它更有用恕我直言.