我正在为Android应用程序实现XMPP客户端。为了获取发送给我的聊天消息,我正在使用Smack的PacketListener。有了应用程序的XMPP部分,一切正常。我可以发送和接收消息。但是我在显示收到的消息时遇到了问题。
为了显示消息,我的应用程序使用ArrayAdapter将它们绑定到ListView。适配器本身工作正常,因为它显示我发送的消息没有任何问题。但收到的消息却不是这样。如果发生与UI的某些交互,则仅显示它们。显然,这是一个线程问题。
如果我没有被Javadoc和Debugger告诉我的错误,PacketListener.processPacket()方法在一个自己的线程中运行,只有当Handler有下一件事要做时,才会执行ListView的更新因此处理它。我现在的问题是,如何告诉处理程序立即处理它?这个工作线程和主线程之间的通信如何工作?由于我自己没有制作Runnable,我不知道如何处理它。
这是代码:
public class Chat extends Activity {
private ArrayList<String> mMessages;
private ArrayAdapter<String> mAdapter;
private ListView mMessageListView;
private EditText mInput;
private String mRecipient;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.chat);
Bundle extras = getIntent().getExtras();
mRecipient = extras.getString("jabberid");
mMessages = new ArrayList<String>();
mMessageListView = (ListView) findViewById(R.id.chatMessageList);
mInput = (EditText) findViewById(R.id.chatInput);
mAdapter = new ArrayAdapter<String>(this, R.layout.channelentry, mMessages);
mAdapter.notifyDataSetChanged();
mMessageListView.setAdapter(mAdapter);
// Getting messages
PacketFilter packetFilter = new MessageTypeFilter(Message.Type.chat);
// XMPPConnection already connected and authenticated
XmppManager.connection.addPacketListener(new PacketListener() {
// Here is where it doesn't display the received message
@Override
public void processPacket(Packet packet) {
Message message = (Message) packet;
displayMessage(message);
}
}, packetFilter);
// Sending messages
Button send = (Button) findViewById(R.id.chatSend);
send.setOnClickListener(new View.OnClickListener() {
// Here everything works just fine
@Override
public void onClick(View v) {
Message message = new Message(mRecipient, Message.Type.chat);
message.setBody(mInput.getText().toString());
XmppManager.connection.sendPacket(message);
displayMessage(message);
}
});
}
private void displayMessage(Message message) {
String sender = message.getFrom();
String chat = sender + " > " + message.getBody();
mAdapter.add(chat);
mAdapter.notifyDataSetChanged();
}
}
答案 0 :(得分:0)
如果您在UI线程中创建了Handler
,则可以使用调用Runnable
方法的displayMessage()
参数调用post()
。或者,您可以再次拨打Activity
类Runnable
的一部分,通过调用displayMessage()
的{{1}}。
我还注意到您从sendPacket()
处理程序中调用onClick()
。您应该确保不阻止UI线程。也许sendPacket()
实际上会产生一个新的线程来进行实际的发送,但是你应该检查它。
答案 1 :(得分:0)
我修改了你的代码如下。希望它现在可以工作了。
public class Chat extends Activity {
private ArrayList<String> mMessages;
private ArrayAdapter<String> mAdapter;
private ListView mMessageListView;
private EditText mInput;
private String mRecipient;
String chat;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.chat);
Bundle extras = getIntent().getExtras();
mRecipient = extras.getString("jabberid");
mMessages = new ArrayList<String>();
mMessageListView = (ListView) findViewById(R.id.chatMessageList);
mInput = (EditText) findViewById(R.id.chatInput);
mAdapter = new ArrayAdapter<String>(this, R.layout.channelentry, mMessages);
mAdapter.notifyDataSetChanged();
mMessageListView.setAdapter(mAdapter);
// Getting messages
PacketFilter packetFilter = new MessageTypeFilter(Message.Type.chat);
// XMPPConnection already connected and authenticated
XmppManager.connection.addPacketListener(new PacketListener() {
// Here is where it doesn't display the received message
@Override
public void processPacket(Packet packet) {
Message message = (Message) packet;
//displayMessage(message);
String sender = message.getFrom();
chat = sender + " > " + message.getBody();
Message msg = handler.obtainMessage();
msg.arg1 = 1;
handler.sendMessage(msg);
}
}, packetFilter);
// Sending messages
Button send = (Button) findViewById(R.id.chatSend);
send.setOnClickListener(new View.OnClickListener() {
// Here everything works just fine
@Override
public void onClick(View v) {
Message message = new Message(mRecipient, Message.Type.chat);
message.setBody(mInput.getText().toString());
XmppManager.connection.sendPacket(message);
displayMessage(message);
}
});
}
private void displayMessage(Message message) {
String sender = message.getFrom();
String chat = sender + " > " + message.getBody();
mAdapter.add(chat);
mAdapter.notifyDataSetChanged();
}
private final Handler handler = new Handler() {
public void handleMessage(Message msg) {
if(msg.arg1 == 1){
mAdapter.add(chat);
mAdapter.notifyDataSetChanged();
}
}
}
}