错误:只有创建视图层次结构的原始线程才能接触其视图
Posted
技术标签:
【中文标题】错误:只有创建视图层次结构的原始线程才能接触其视图【英文标题】:error: Only the original thread that created a view hierarchy can touch its views 【发布时间】:2011-07-03 02:34:30 【问题描述】:您好,感谢您查看我的问题。 我是 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);
);
【问题讨论】:
【参考方案1】:在你的 run() 方法中:
Message msg = new Message();
String textTochange = "text";
msg.obj = textTochange;
mHandler.sendMessage(msg);
在你的 UI 线程中创建 mHandler;
Handler mHandler = new Handler()
@Override
public void handleMessage(Message msg)
String text = (String)msg.obj;
//call setText here
;
【讨论】:
handleMessage 似乎不是 Handler 的超类方法;为什么你有@Override?尝试此操作时出现错误。【参考方案2】:设置文本时您不在 UI 线程上。如果你想处理 UI 项目,你需要在 UI 上。在 UI 线程上创建一个消息处理程序,将您的消息发布到它并从 UI 线程上的处理程序调用 setText。
【讨论】:
是的,我在其他问题中也看到过类似的答案,只是太笼统了。不是你错了,而是像我这样的人有点慢。不过非常感谢我解决了【参考方案3】:您可以在任何时候在线程中执行此操作:
msgToServer.post(new Runnable()
public void run()
msgToServer.setText("your text here");
【讨论】:
我想你误解了我的意思。但我使用处理程序解决了它。谢谢你的回答。【参考方案4】:您的问题是您只能在 UI 线程上执行某些交互。这是其中之一。
看起来你可能想要使用 AsyncTask
http://developer.android.com/reference/android/os/AsyncTask.html
基本上,您可以将 Runnable 设为 AsyncTask,并在 onProgressUpdate 中执行 setText,这将在 UIThread 上运行。
【讨论】:
我已经调查过了,但该页面上的内容对我来说毫无意义。有什么地方可以找 AsyncTask 的例子吗? (我用处理程序解决了它)谢谢!【参考方案5】:如果您想使用 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();
【讨论】:
以上是关于错误:只有创建视图层次结构的原始线程才能接触其视图的主要内容,如果未能解决你的问题,请参考以下文章
Android “只有创建视图层次结构的原始线程才能接触其视图。” for循环中的错误[重复]
致命例外:JavaBridge - 只有创建视图层次结构的原始线程才能接触其视图
Android错误:只有创建视图层次结构的原始线程才能触摸其视图[重复]