【问题标题】:Android: Communicate with worker thread to send messagesAndroid:与工作线程通信以发送消息
【发布时间】:2014-09-19 10:19:39
【问题描述】:

我正在尝试通过 tcp 将消息从一个 android 设备发送到另一个设备。发送设备发送到用作服务器的 PC,然后将消息发送到其他设备。 为了接收消息,我运行了一个与 UI 线程并行的线程,它使用处理程序更新用户界面以显示消息。这很好用。

现在我正在使用 AsyncTask 发送消息,它创建一个套接字,然后发送消息,然后再次关闭套接字。所以每次我想发送消息时,我都必须连接和断开连接。

public class SendTask extends AsyncTask<String, Void, Void> {

static final String TAG = "SendTask";

private Socket soc;
private String theIp;
private int thePort;

public SendTask(String pIp, int pPort){
    theIp = pIp;
    thePort = pPort;
}

@Override
protected Void doInBackground(String... arg0) {

    try {
        soc = new Socket(theIp, thePort);
        soc.getOutputStream().write(arg0[0].getBytes());
        soc.close();
    } catch (Exception e) {
        Log.d(TAG, "failed to create socket");      
        e.printStackTrace();
    }

    return null;
}

}

我宁愿有一个解决方案,我创建一个打开套接字的线程,然后每次单击按钮时发送从 EditText 接收的文本。有没有类似于接收线程的解决方案?我正在努力如何告诉创建的线程何时发送消息而不从该线程访问 UI。

发送线程如下:

public class ReceiveClient implements Runnable {

static final String TAG = "ReceiveClient";

public static final int NEW_INPUT = 101;

private Socket soc;
private String theIp;
private int thePort;
Handler handler;

public ReceiveClient(String pIp, int pPort, Handler pHandler){
    this.theIp = pIp;
    this.thePort = pPort;
    handler = pHandler;
}

@Override
public void run() {
    Log.d(TAG, "try to create socket");
    try {
        soc = new Socket(theIp, thePort);
    } catch (Exception e) {
        Log.d(TAG, "failed to create socket");      
        e.printStackTrace();
    }
    Log.d(TAG, "running");
    try {
        while (!Thread.currentThread().isInterrupted()) {
            byte b[] = new byte[16];
            int count = soc.getInputStream().read(b, 0, 16);
            if(count > 0){
                String s = new String(b);
                Log.d(TAG, "received: " + s);
                displayMessage(s);
                }
            }
        Log.d(TAG, "done");
        }catch (Exception e) {
            System.err.println(e);
    }
}

private void displayMessage(String text){
    Message msg = handler.obtainMessage();
    msg.what = NEW_INPUT;
    msg.obj = text;
    handler.sendMessage(msg);
}
}

【问题讨论】:

  • 你需要使用 Handler 但相反...试试 HandlerThread

标签: java android multithreading sockets tcp


【解决方案1】:

我建议你使用某种阻塞队列。在单独的线程中处理读取和写入 - 这是线程安全的,即如果一个线程从套接字读取而另一个线程写入它,则不会有任何冲突。

您的阅读器线程需要改进 - InputStream.read 将在没有可用输入时阻塞,因此您的 Thread.isInterrupted 检查是无用的。相反,我建议您跳过 isInterrupted 检查并在您想停止阅读时关闭套接字,这将导致您的 read() 解除阻塞。

在你的作家线程中做这样的事情

 private ArrayBlockingQueue<String> writerQueue = new ArrayBlockingQueue<String>( 10 );
 private String stopSignal = "whatever";       

 public void stopWriter() { // this can safely called from other threads and will cause writer thread to stop
     writerQueue.put( stopSignal );     
 } 

 // this can also safely called from other threads
 public void sendMessage( String newMessage ) {
     writerQueue.put( newMessage );
 }

 @Override
 public void run() {
     String currentMessage = writerQueue.take(); // if there are no messages in queue this will block
     if( currentMessage == stopSignal ) // == comparison here is correct! we want to check for object equality 
         return; // stop signal received
     // write your string here
 }  

在您的 UI 中使用发送消息

writerThread.sendMessage( "Whatever you want to send );

当完成线程

writerThread.stopWriter();

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-07-21
    • 2012-05-24
    • 2018-08-29
    • 2013-10-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多