我是Android开发人员的新手,但不是Java新手。
一条黄金法则是永远不会阻止GUI线程,也不会阻塞主线程。
我面临的问题是我的应用可以向服务器发送消息,服务器会显示消息。当我的服务器(PC)将消息发送回我的Android应用程序时,应用程序会收到消息,这很明显是由于log method
。
控制台显示从服务器发送的消息,但GUI应用程序没有,这是因为它冻结了。
我所做的是在另一个线程中设置一个线程。 `主线程>线程(连接到服务器)>线程(侦听传入的消息)>线程(Android Gui线程)。
这里的问题是;程序冻结,活动停止响应。对话框窗口确实显示从服务器发送的消息。
我的问题是,当我没有阻止任何线程时,为什么应用程序会冻结?
private void ConnectButtonPress() {
btnConnect.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
btnConnect.setVisibility(View.GONE);
btnDisconnect.setVisibility(View.VISIBLE);
btnSend.setEnabled(true);
enterET.setEnabled(true);
new Thread(new Runnable() {
public void run(){
try {
socket = new Socket(IPAddressET.getText().toString(), Integer.parseInt(portET.getText().toString())); //connect to server
input = new Scanner(socket.getInputStream());
pw = new PrintWriter(socket.getOutputStream(), true);
pw.println(usersName); //write the message to output stream
pw.flush();
new Thread(new Runnable() {
@Override
public void run() {
while (true){//this is where the problem is
try {
input = new Scanner(socket.getInputStream());
} catch (IOException e) {
e.printStackTrace();
}
String message = input.nextLine();
Log.i("LOL",message);
runOnUiThread(new Runnable() {
@Override
public void run() {
String message = input.nextLine();
displayMessages.append(message +"\n");
}
});
}
}
}).start();
//pw.close();
//pw.close(); //closing the connection
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}).start();
}
});
}
答案 0 :(得分:2)
好吧,这个街区:
runOnUiThread(new Runnable() {
@Override
public void run() {
String message = input.nextLine();
displayMessages.append(message +"\n");
}
});
在while
循环内无限期运行,因此会阻塞主线程。为什么需要在主线程中构建displayMessages
?我想你可以将displayMessages.append(message +"\n");
放在while
循环中。
答案 1 :(得分:1)
如果我没错,input.nextLine();
会阻止线程直到从服务器收到消息。
因此,如果我是正确的,当您从服务器收到新消息时,您将在主线程上运行以更改您拥有的文本视图...但是在runOnUiThread中您再次调用input.nextLine();
,当你已经在String message = input.nextLine();
电话会议之前阅读了它的值(runOnUiThread(new Runnable() {...
)。
这基本上会导致您的主线程等待来自服务器的新消息。您只需使用您已有的值,或者,我想您也可以使用hasNextLine()
。