web-dev-qa-db-de.com

Aktualisieren der Android-Benutzeroberfläche mithilfe von Threads

Ich schreibe eine Android Chat App. Ich höre auf Verbindungen und erhalte Daten und kann sie im Log.d sehen. Wenn ich jedoch versuche, meine Benutzeroberfläche zu aktualisieren, stürzt die Anwendung ab. 

Code-Auszug:  

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

    }
} 

und zum Aktualisieren der von mir verwendeten Benutzeroberfläche: 

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

Die Anwendung stürzt ständig ab.

27
AhmadAssaf

Sie können nichts im UI-Thread von einem Hintergrundthread aus anfassen . Dazu verwenden Sie Handlers. Initialisieren Sie Ihren Hintergrund thread, indem Sie ein Handler-Objekt übergeben. Wenn Daten eingehen, verwenden Sie handler, um eine Nachricht an die Benutzeroberfläche zu senden. Wenn die Nachricht aus dem Hintergrund thread kommt, aktualisieren Sie einfach die Views in der Benutzeroberfläche.

Beispiel-Code-Snippet:

im Hintergrundthread: 

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

im UI-Thread:

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

und übergeben Sie die handler an den Hintergrund thread.

55
Franco

Sie können keine Benutzeroberflächenelemente in einem Thread ohne Benutzeroberfläche ändern. Versuchen Sie es mit runOnUiThread .

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

Oder benutzen Sie einfach AsyncTask , es ist IMHO nützlicher.

8
Olsavage

Verwenden Sie die Methode " this ", um Ihre Benutzeroberfläche vom Worker-Thread zu aktualisieren. Hier wird es gut erklärt. 

Hinweis: - Wenn Sie progressbar.setProgress(progress) verwenden, können Sie direkt vom Worker thread aus aktualisieren, da die ProgressBar intern die setProgress()-Methode mit Handler aufruft.

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