使用线程更新Android UI

时间:2011-03-03 18:39:26

标签: android user-interface

我正在写一个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());
        }

    }
} 

并更新我使用的用户界面:

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

应用程序不断崩溃。

5 个答案:

答案 0 :(得分:70)

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

runOnUiThread(new Runnable(){
    @Override
    public void run(){
        // change UI elements here
    }
});

答案 1 :(得分:58)

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

示例代码段:

在后台主题中:

if(dataArrives){
    Message msg = handler.obtainMessage();
    msg.what = UPDATE_IMAGE;
    msg.obj = bitmap;
    msg.arg1 = index;
    handler.sendMessage(msg);
}
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);
  }
};

并将handler传递给后台thread

答案 2 :(得分:8)

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

答案 3 :(得分:0)

使用this方法从工作线程更新您的UI,这里解释得很好。

注意: - 如果您使用的是Const idleTime = 900 'seconds Dim Start Sub StartTimer() Start = Timer Do While Timer < Start + idleTime DoEvents Loop Application.DisplayAlerts = False ActiveWorkbook.Close True Application.DisplayAlerts = True End Sub ,则可以直接从工作人员progressbar.setProgress(progress)进行更新,因为thread内部使用了ProgressBar方法setProgress()

答案 4 :(得分:0)

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