错误:只有创build视图层次结构的原始线程才能触及其视图

嗨,谢谢你看我的问题。 我是一个C中的中间程序员,但是一个Android新手。 我一直在试图让聊天编程工作。 假设以下代码中的其他内容完美无缺。 我想问的一个问题是,当我尝试从运行的线程中设置Text()时 ,我得到上面的exception。 我看了许多网站,也在这里。 发现了很多东西,但我真的不明白。 请以最简单的方式向我解释,或者如果可能的话给我一些简单的修复。

非常感谢你!!

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 "错误:只有创build视图层次结构的原始线程才能触及其视图"

在你的run()方法中:

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

在UI线程中创buildmHandler;

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

设置文本时,您不在UI线程中。 如果你想在UI项目上工作,你需要在UI上。 在UI线程上创build一个消息处理程序,将消息发送给它,并在UI线程上从处理程序调用setText。

你可以在线程中执行此操作:

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

你的问题是,你只能在UI线程上做某些交互。 这是其中之一。

看起来你可能想要使用AsyncTask

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

基本上你可以使你的Runnable成为一个AsyncTask,并在onProgressUpdate中执行setText,它将在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"); } 

}

执行代码:

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