0

Android アプリケーション用の XMPP クライアントを実装しています。私に送信されたチャット メッセージを取得するために、Smack の PacketListener を使用しています。アプリケーションの XMPP 部分では、すべて正常に動作します。メッセージを送受信できます。しかし、受信したメッセージの表示に問題があります。

メッセージを表示するために、アプリケーションはメッセージを ListView にバインドする ArrayAdapter を使用します。私が送信したメッセージは問題なく表示されるため、アダプタ自体は正常に動作します。しかし、受信したメッセージはそうではありません。UI との対話が発生した場合にのみ表示されます。どうやら、これはスレッドの問題です。

Javadoc とデバッガーが教えてくれたことに間違いがなければ、Pac​​ketListener.processPacket() メソッドは独自のスレッドで実行され、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();
    }
}
4

2 に答える 2

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

    }
于 2011-08-19T12:13:43.543 に答える
0

HandlerUI スレッド内にを作成すると、メソッドを呼び出す引数をpost()使用してそれを呼び出すことができます。または、クラスの一部であるを再度呼び出し、を呼び出すを渡すこともできます。RunnabledisplayMessage()runOnUiThread()ActivityRunnabledisplayMessage()

また、ハンドラーsendPacket()から呼び出していることにも気付きました。onClick()UI スレッドをブロックしないようにする必要があります。おそらくsendPacket()実際に新しいスレッドを生成して実際の送信を行いますが、これは確認する必要があります。

于 2011-08-19T11:54:09.347 に答える