Ошибка: только исходный поток, создавший иерархию представлений, может коснуться его представлений

Привет, спасибо, что посмотрели на мой вопрос. Я – программист на C, но новичок в Android. Я пытаюсь работать в чате. Предполагая, что все остальное в коде ниже работает отлично. Один вопрос, который я хотел бы спросить, – это когда я пытаюсь setText () из потока, выполняющего, я получаю исключение выше. Я просмотрел многие сайты и здесь. Нашел много вещей, но я действительно не понимаю. Пожалуйста, объясните мне самым простым способом или предложите мне несколько простых исправлений, если это возможно.

Большое спасибо!!

public class chatter extends Activity { private String name = "Unknown User"; /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); final EditText msgToServer = (EditText) findViewById(R.id.msgBox); final EditText chatFromServer = (EditText) findViewById(R.id.chatBox); final Button MsgToServer = (Button) findViewById(R.id.sendButton); Socket socket = null; String ipAddress = "192.168.1.103"; try { InetAddress serverAddr = InetAddress.getByName(ipAddress); Socket socketMain = new Socket(serverAddr, 4444); socket = socketMain; } catch (IOException e) { // TODO Auto-generated catch block Log.e("TCP", "error", e); } final OutMsg outMsg = new OutMsg(socket); Thread msgSenderThread = new Thread(outMsg); msgSenderThread.start(); //chatFromServer.post(new InMsg(socket, chatFromServer)); Thread msgReceiverThread = new Thread(new InMsg(socket, chatFromServer)); msgReceiverThread.start(); MsgToServer.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { String msgToServerString; msgToServerString = msgToServer.getText().toString(); outMsg.message = name + ": " + msgToServerString; outMsg.readyToSend = true; msgToServer.setText(""); } }); } public void updateResultsInUi (String msg) { final EditText chatFromServer = (EditText) findViewById(R.id.chatBox); chatFromServer.setText(msg); } public class InMsg implements Runnable { Socket socket; EditText chatFromServer; public InMsg(Socket socket, EditText chatFromServer) { this.socket = socket; this.chatFromServer = chatFromServer; } public void run(){ try { BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream())); String str = "FIRSTMESSAGEFROMSERVER"; while (true) { if (str.equals("FIRSTMESSAGEFROMSERVER")) str = in.readLine(); else str = str + "\n" + in.readLine(); Log.e("TCP", "got the message: " + str); //Here is where went wrong****************** chatFromServer.setText(str); //****************************************** } } catch (IOException e) { // TODO Auto-generated catch block Log.e("TCP", "error in receiving", e); } } } @Override public boolean onCreateOptionsMenu(Menu menu) { MenuInflater inflater = getMenuInflater(); inflater.inflate(R.menu.menu, menu); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { // Handle item selection switch (item.getItemId()) { case R.id.setNameMenu: setname(); return true; default: return super.onOptionsItemSelected(item); } } public void populateChatBox (String msgFromS) { Log.e("TCP", "going in to popC"); final EditText textNameInput = (EditText) findViewById(R.id.nameBox); Log.e("TCP", " popC"); textNameInput.setText(msgFromS); Log.e("TCP", "going out from popC"); } public void setname() { setContentView(R.layout.custom_dialog); final EditText textNameInput = (EditText) findViewById(R.id.nameBox); Button submitNameButton = (Button) findViewById(R.id.submitNameButton); submitNameButton.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { String nameinput = textNameInput.getText().toString(); if (!name.equals("")) name = nameinput; setContentView(R.layout.main); } }); } } 

Solutions Collecting From Web of "Ошибка: только исходный поток, создавший иерархию представлений, может коснуться его представлений"

В вашем методе run ():

 Message msg = new Message(); String textTochange = "text"; msg.obj = textTochange; mHandler.sendMessage(msg); 

Создайте mHandler в потоке пользовательского интерфейса;

 Handler mHandler = new Handler() { @Override public void handleMessage(Message msg) { String text = (String)msg.obj; //call setText here } }; 

При установке текста вы не находитесь в потоке пользовательского интерфейса. Вы должны быть в пользовательском интерфейсе, если хотите работать с элементами пользовательского интерфейса. Создайте обработчик сообщений в потоке пользовательского интерфейса, разместите его сообщения и вызовите setText из обработчика в потоке пользовательского интерфейса.

Вы можете делать это всякий раз, когда вы находитесь в потоке:

 msgToServer.post(new Runnable() { public void run() { msgToServer.setText("your text here"); } } 

Ваша проблема в том, что есть определенные взаимодействия, которые вы можете делать только в потоке пользовательского интерфейса. Это одна из них.

Похоже, вы можете использовать AsyncTask

http://developer.android.com/reference/android/os/AsyncTask.html

В основном вы можете сделать свой Runnable ayncTask и сделать setText в onProgressUpdate, который запускается на UIThread.

Если вы хотите использовать AsyncTask для работы в фоновом режиме, я бы это сделал:

 public class UpdateTextProgress_Task extends AsyncTask<Void,String,Void> { Socket socket; EditText chatFromServer; UpdateTextProgress_Task(EditText chatFromServer, Socket socket){ this.socket = socket; this.chatFromServer = chatFromServer; } @Override protected Void doInBackground(Void... params) { try { BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream())); String str = "FIRSTMESSAGEFROMSERVER"; while(true){ if (str.equals("FIRSTMESSAGEFROMSERVER")){ str = in.readLine(); } else{ str = str + "\n" + in.readLine(); } Log.e("TCP", "got the message: " + str); publishProgress(str); // calls the onProgressUpdate method }catch (IOException e) { Log.e("UpdateTextProgress", e.getMessage()); } return null; } @Override protected void onProgressUpdate(String... progress) { chatFromServer.setText(progress[0]); //now we are on the UI thread so we can update our EditText } @Override protected void onPostExecute(Void result) { super.onPostExecute(result); Log.e("UpdateTextProgress", "Finished"); } в public class UpdateTextProgress_Task extends AsyncTask<Void,String,Void> { Socket socket; EditText chatFromServer; UpdateTextProgress_Task(EditText chatFromServer, Socket socket){ this.socket = socket; this.chatFromServer = chatFromServer; } @Override protected Void doInBackground(Void... params) { try { BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream())); String str = "FIRSTMESSAGEFROMSERVER"; while(true){ if (str.equals("FIRSTMESSAGEFROMSERVER")){ str = in.readLine(); } else{ str = str + "\n" + in.readLine(); } Log.e("TCP", "got the message: " + str); publishProgress(str); // calls the onProgressUpdate method }catch (IOException e) { Log.e("UpdateTextProgress", e.getMessage()); } return null; } @Override protected void onProgressUpdate(String... progress) { chatFromServer.setText(progress[0]); //now we are on the UI thread so we can update our EditText } @Override protected void onPostExecute(Void result) { super.onPostExecute(result); Log.e("UpdateTextProgress", "Finished"); } 

}

Чтобы выполнить код:

 UpdateTextProgress_Task task = new UpdateTextProgress_Task(chatFromServer,socket); task.execute();