gpt4 book ai didi

java - Android:Thread Runnable 和 Handler.post 问题 - 在 Run 方法中(Handler.postXX 没有按预期运行)

转载 作者:行者123 更新时间:2023-11-30 03:51:33 25 4
gpt4 key购买 nike

我有一个用作 TCP 客户端的 TCP 套接字,用于不断地 从服务器读取传入数据——直到客户端或服务器断开连接。我不知道任何其他方法,但在不同的 Runnable 线程中使用 while (true) 循环并在其中(在 while 循环中)检查传入数据。接收到的数据需要打印在EditText中。

我遇到的问题是从 Handler.post(...) 更新文本。

我知道:

  • 为了与 Android 3.0 及更高版本建立 TCP 连接,我需要将 TCP 代码放在 new Thread(...)AsyncTask 因为默认情况下已启用严格模式,我不想禁用它。

  • 我知道为了从 Android 中的新线程更新 UI,如果我使用 ThreadonProgressUpdate<,我需要使用 Handler.post()/strong> 通过 publichProgress 如果我使用 AsyncTask 并且我知道如何使用所有这些,但是我遇到了 weird 令人沮丧的问题。

所以,我想做的就是:

  • 永久监听服务器
  • 一旦服务器向我发送一条消息,例如:“w”或“a”或“n”,我就会立即将其显示在 EditText 上。您可以将其视为 telnet session ,但我需要“更多”精度高于 telnet,因为我想处理每个字节,甚至是不可打印的字节,所以我不想无论如何都想使用readLine。我必须一次读取一个字节或获取一个字节缓冲区,然后通过遍历缓冲区分别处理它们。我一次带一个字节。

这是我的代码,请注意我在 handle.response 上面的评论,看看我遇到的问题。我希望你能解决这个问题。

代码非常简洁,我删除了这个示例的很多错误检查部分。

我有一个新类:ThreadClientInput:

public class ThreadClientInput  implements Runnable {

InputStream inputStream;
MainActivity mainActivity;
Handler handler = new Handler();
int NextByte = 0;

public ThreadClientInput(MainActivity ma)
{
mainActivity = ma;
}

@Override
public void run()
{
////////////////////////////////////////////////////////////////
// Run the sensitive code that requires us to create this thread
try {
mainActivity.tcp_Client = new Socket("192.168.1.90", 23);
}
catch (Exception e){Log.e("EXEPTION:", e.getMessage().toString());return;}
////////////////////////////////////////////////////////////////


// Only try to get the inputStream if we have a successful connection
if (mainActivity.tcp_Client != null)
{
try
{
inputStream = mainActivity.tcp_Client.getInputStream();
}
catch (Exception e){Log.e("EXEPTION:", e.getMessage().toString()); return;}
}


/////////////////////////////////////////////
/////////////////////////////////////////////
// Update the text on the "Connect" button
handler.post(new Runnable()
{
@Override
public void run()
{ mainActivity.btn_Connect.setText("Connected");}
});
/////////////////////////////////////////////
/////////////////////////////////////////////

try
{

// I need to constantly read the data until we manually disconnect or
// the server drops the connection
while (true)
{
// Get the next byte
// I do not want to use "readline()" from a BufferedReader etc because I need to know exactly what's coming in
// I need to process every single byte
NextByte = inputStream.read();

if (NextByte > -1)
{
Log.e("in (While loop):", Character.toString((char)NextByte));

*** Here is the problem ****
// Update the EditText and this is where the problem starts
// if the server sends "1234", the Log.e() above will display everything correctly: "1234"
// however the handler.post below will run at the end of the last byte so the
// the EditText as well as the second Log.e below within the handle.post will display: "1444" or "4444" or "2444"
// So the handler.post does *not* run immediately even if I try handle.postAtFrontOfQueue()
// If the server sends "12345678", again, Log.e() above will display everything correctly: "12345678"
// however the handler.post below will run at the end of the last byte again
// and I will get "88888888" (most of the time) or "18888888"

//

handler.post(new Runnable()
{
@Override
public void run()
{
mainActivity.et_Response.setText(mainActivity.et_Response.getText() + Character.toString((char)NextByte));
Log.e("In handler.post:", Character.toString((char)NextByte));
}
});
}
}
}
catch (Exception e){Log.e("EXEPTION:", e.getMessage().toString());}
}}

我尝试了各种变体,包括使用 runOnUiThread 和 AsyncTask 的变体,但我得到的结果都是一样的。我出去了,我什么都没有。目前我正在阅读一些关于 Handle.post 方法的文档,看看我是否能理解。

我希望你有一个解决方案,我知道“while (true)”不是一个好的做法,但我可以通过设置标志从线程外部打破循环,但我没有不知道还有什么其他方法可以做到这一点。

最佳答案

我不确定您如何能够从 public void run() 访问 NextByte 而无需将其定义为 final !?

  • 如果您希望处理程序将消息发布到 Activity UI 线程,您应该在 Activity 类中 创建它,以便它可以访问其 Looper。

我可以为您的问题想到以下两种解决方案:

1- 使用自定义 Runnable 类,您将 NextByte 值作为变量传递给它,例如

   handler.post(new MyRunnable(NextByte));

MyRunnable 可以是这样的:

  class MyRunnable implements Runnable{
int byteData;
public MyRunnable(int byteData){
this.byteData = byteData;
}

public void run(){ // update the EditText}
}

2- 使用 handler.sendMessage();并将 NextByte 添加为消息参数,例如

 Message msg = new Message();
msg.arg1 = NextBye
handler.sendMessage(msg);

你的处理程序应该定义如下:

handler = new Handler() {
@Override
public void handleMessage(Message msg) {
int nextByte = msg.arg1;
// update the EditText
}
};

关于java - Android:Thread Runnable 和 Handler.post 问题 - 在 Run 方法中(Handler.postXX 没有按预期运行),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14078727/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com