Я пишу простое приложение, используемое для связи между сервером и приложением в локальной сети. Написание и получение сообщений работает без проблем. Но я не могу отображать сообщения, полученные в Textview.
Для приема входящих сообщений я использую (рабочий) поток. Когда я что-то получаю, я отправляю сообщение обработчику в mainthread, который затем должен отображать сообщение в Textview.
Но каждый раз, когда обработчик пытается отобразить сообщение, я получаю исключение:
"Только исходный поток, создавший иерархию представлений, может коснуться его представлений".
Я искал многие веб-сайты, в том числе и этот, чтобы найти решение, но все еще не мог решить проблему. Пожалуйста, помогите мне.
Код:
public class TCPClientActivity extends Activity {
BufferedWriter output;
Socket s = new Socket();
//my handler
private Handler mHandler;
//where I want to display the message
private TextView lblChat;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.tcpclient);
Button btnConnect = (Button)findViewById(R.id.btnConnect);
Button btnSend = (Button) findViewById(R.id.btnSend);
//creating the TextView
lblChat = (TextView) findViewById(R.id.lblChat);
final EditText tbIP = (EditText) findViewById(R.id.tbIP);
final EditText tbInput = (EditText) findViewById(R.id.tbInput);
//creating the handler
mHandler = new Handler()
{
@Override
public void handleMessage(Message msg)
{
switch(msg.what)
{
case 1:
{
lblChat.append("Received: " + msg.obj + "\r\n" );
}
}
}
};
}
//Thread in which I receive incoming Messages from the server
Thread communication = new Thread()
{
@Override
public void run()
{
String finalText = "";
while(true)
{
try
{
DataInputStream inputStream = new DataInputStream(s.getInputStream());
int bytesRead;
byte[] b = new byte[4096];
bytesRead = inputStream.read(b,0,b.length);
finalText = EncodingUtils.getAsciiString(b);
//sending the message to the handler
Message msg = new Message();
msg.what = 1;
msg.obj = finalText;
mHandler.handleMessage(msg);
}
//android.view.ViewRoot$CalledFromWrongThreadException:
//Only the original thread that created a view hierarchy can touch its views.
//That the exception I get when running the program
catch (Exception e)
{
e.printStackTrace();
}
}
}
};
//method where I connect to the server
private void connectToServer(String ip)
{
try
{
if(!ip.equals(""))
{
s = new Socket(ip, 3000);
}
else
{
s = new Socket("10.0.0.143", 3000);
}
output = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
output.write("Android Connected");
output.flush();
// new CommuTask().execute();
//starting the thread
communication.start();
// s.close();
}
catch(UnknownHostException e)
{
e.printStackTrace();
try {
s.close();
} catch (IOException e1) {
e1.printStackTrace();
}
}
catch(IOException e)
{
e.printStackTrace();
try {
s.close();
} catch (IOException e1) {
e1.printStackTrace();
}
}
}
}
Вы вызываете метод непосредственно на обработчике (поэтому на рабочем рабочем потоке) вместо нажатия сообщения
Вместо:
mHandler.handleMessage(msg);
ты захочешь:
mHandler.sendMessage(msg);
Ссылка: http://developer.android.com/reference/android/os/Handler.html#sendMessage(android.os.Message)
Вместо этого:
mHandler.handleMessage(msg);
Использовать это:
mHandler.sendMessage(msg);