J'écris une application de chat Android. J'écoute les connexions et je reçois des données que je peux voir dans le Log.d
, mais chaque fois que je tente de mettre à jour mon interface utilisateur, l'application se bloque.
Extrait de code:
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());
}
}
}
et pour mettre à jour l'interface utilisateur que j'utilise:
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());
}
L'application continue à planter.
Vous ne pouvez rien toucher dans le fil de l'interface utilisateur à partir d'un fil de fond , pour ce faire, utilisez Handlers
, initialisez votre fond thread
en lui passant un objet Handler
. Lorsque les données arrivent, utilisez la variable handler
pour envoyer un message à l'interface utilisateur. Dans l'interface utilisateur lorsque le message de la thread
d'arrière-plan arrive, il suffit de mettre à jour la Views
.
Exemple d'extrait de code:
dans le fil de fond:
if(dataArrives){
Message msg = handler.obtainMessage();
msg.what = UPDATE_IMAGE;
msg.obj = bitmap;
msg.arg1 = index;
handler.sendMessage(msg);
}
dans le fil de l'interface utilisateur:
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);
}
};
et passez la handler
à l'arrière-plan thread
.
Vous ne pouvez pas modifier les éléments d'interface utilisateur à partir d'un thread non-UI. Essayez d’utiliser runOnUiThread .
runOnUiThread(new Runnable(){
@Override
public void run(){
// change UI elements here
}
});
Ou utilisez simplement AsyncTask , il est plus utile à mon humble avis.
Utilisez this pour mettre à jour votre interface utilisateur à partir du thread de travail, voici comment cela est expliqué.
Remarque: - Si vous utilisez progressbar.setProgress(progress)
, vous pouvez effectuer une mise à jour directement à partir de l'agent thread
car la méthode ProgressBar
appelle en interne la méthode setProgress()
à l'aide de Handler
.
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();
}