Java Android:Thread Runnable和Handler.post在run方法中出现问题-(Handler.postx未按预期时间运行)
我有一个TCP套接字用作TCP客户端,用于不断地从服务器读取传入数据,直到客户端或服务器断开连接。我不知道还有其他方法,但在不同的可运行线程中使用while(true)循环,并在其中(while循环)检查传入数据。接收到的数据需要打印在编辑文本中 我遇到的问题是从Handler.post(…)更新文本 我知道:Java Android:Thread Runnable和Handler.post在run方法中出现问题-(Handler.postx未按预期时间运行),java,android,Java,Android,我有一个TCP套接字用作TCP客户端,用于不断地从服务器读取传入数据,直到客户端或服务器断开连接。我不知道还有其他方法,但在不同的可运行线程中使用while(true)循环,并在其中(while循环)检查传入数据。接收到的数据需要打印在编辑文本中 我遇到的问题是从Handler.post(…)更新文本 我知道: 为了使用Android 3.0及以上版本创建TCP连接,我需要将TCP代码放置在新线程(…)或异步任务中,因为默认情况下已启用严格模式,我不想禁用它 我知道为了从Android中的新线
- 为了使用Android 3.0及以上版本创建TCP连接,我需要将TCP代码放置在新线程(…)或异步任务中,因为默认情况下已启用严格模式,我不想禁用它
- 我知道为了从Android中的新线程更新UI,我需要使用Handler.post()如果我使用线程或通过publichProgress进行的onProgressUpdate,如果我使用AsyncTask,我知道如何使用所有这些,但我在这两个方面都遇到了奇怪的令人沮丧的问题
- 永久监听服务器
- 一旦服务器向我发送消息,例如:“w”或“a”或“n”,我立即将其显示在EditText上。您可以将其视为telnet会话,但我需要“更多” 精度比telnet高,因为我想处理每个字节,甚至是不可打印的字节,所以我确实不无论如何都想使用readLine。I必须一次读取一个字节,或者获取一个字节缓冲区,然后通过迭代缓冲区分别处理它们。我一次用一个字节
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
)
但不将其定义为最终版本
- 如果您希望处理程序将消息发布到活动UI线程,您应该在活动类中创建它,以便它可以访问其循环器
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
}
};
我不确定您如何能够从
public void run()
访问NextByte
,而不将其定义为final
- 如果您希望处理程序将消息发布到活动UI线程,您应该在活动类中创建它,以便它可以访问其循环器
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
}
};
问题已经解决了 这就是我做的 在MainActivity.java(主文件)中,在MainActivity类中
public static class MyRunnable implements Runnable {
int currentByte = 0;
public MyRunnable(int b){
currentByte = b;
}
@Override
public void run()
{
mainActivity.et_Response.setText(mainActivity.et_Response.getText() + Character.toString((char)currentByte));
}
}
我有一句话mainActivity=this在onCreate中,然后在ThreadClientInput.run中运行
try {
while (true)
{
NextByte = inputStream.read();
// if the server drops the connection, break out the loop
if (NextByte < 0) break;
handler.post(new MainActivity.MyRunnable(NextByte));
}
}
catch (Exception e) {
Log.e("EXCEPTION", e.getMessage());
}
试试看{
while(true)
{
NextByte=inputStream.read();
//如果服务器断开连接,则中断循环
如果(下一字节<0)中断;
handler.post(newmainActivity.MyRunnable(NextByte));
}
}
捕获(例外e){
Log.e(“异常”,e.getMessage());
}
在此之后,handler.post将在正确和预期的时间被正确调用。iTech获得了全部荣誉。问题已得到解决 这就是我做的 在MainActivity.java(主文件)中,在MainActivity类中
public static class MyRunnable implements Runnable {
int currentByte = 0;
public MyRunnable(int b){
currentByte = b;
}
@Override
public void run()
{
mainActivity.et_Response.setText(mainActivity.et_Response.getText() + Character.toString((char)currentByte));
}
}
我有一句话mainActivity=this在onCreate中,然后在ThreadClientInput.run中运行
try {
while (true)
{
NextByte = inputStream.read();
// if the server drops the connection, break out the loop
if (NextByte < 0) break;
handler.post(new MainActivity.MyRunnable(NextByte));
}
}
catch (Exception e) {
Log.e("EXCEPTION", e.getMessage());
}
试试看{
while(true)
{
NextByte=inputStream.read();
//如果服务器断开连接,则中断循环
如果(下一字节<0)中断;
handler.post(newmainActivity.MyRunnable(NextByte));
}
}
捕获(例外e){
Log.e(“异常”,e.getMessage());
}
在此之后,handler.post将在正确和预期的时间被正确调用。完全归功于iTech。就解决方案1而言,它不起作用。我得到相同的输出。我在MainActivity.java中创建了一个名为updateText(intb)的方法,其中有一个handler.post来更新文本。我在NextByte=inputStream.read()之后立即调用此方法;但我得到了相同的输出。对于解决方案2,我不熟悉som的Handler.sendMessage概念