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

Android 错误:只有创建视图层次结构的原始线程才能接触其视图,android,view,hierarchy,settext,Android,View,Hierarchy,Settext,你好,谢谢你看我的问题。 我是一名C语言的中级程序员,但却是一名Android新手。我一直在努力让聊天程序正常工作。假设下面代码中的所有其他内容都能完美工作。我想问的一个问题是,当我试图从运行的线程中setText()时,我会遇到上面的异常。我看了很多网站,这里也是。发现很多东西,但我真的不明白。请以最简单的方式向我解释,或者如果可能的话,为我提供一些简单的解决方案 非常感谢 public class chatter extends Activity { private String name

你好,谢谢你看我的问题。 我是一名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);
        }
    });
}
}

设置文本时,您不在UI线程上。如果要处理UI项,您需要在UI上。在UI线程上创建消息处理程序,向其发布消息,并从UI线程上的处理程序调用setText。

无论何时在线程中,都可以执行此操作:

msgToServer.post(new Runnable() {
    public void run() {
        msgToServer.setText("your text here");
    }
}
在run()方法中:

在UI线程中创建mHandler

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

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

看起来您可能想要使用AsyncTask


基本上,您可以将您的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");
}

是的,我在其他问题上也看到过类似的答案,只是太笼统了。不是你错了,而是像我这样的人有点慢。但非常感谢你我解决了它我想你误解了我。但我用处理器解决了这个问题。谢谢你的回答。我已经调查过了,但那一页对我来说毫无意义。有什么地方我可以为AsyncTask找个例子吗?(我用handler解决了这个问题)谢谢!handleMessage似乎不是处理程序的超类方法;为什么有@Override?我尝试此操作时出错。
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();