嗨,谢谢你看我的问题。 我是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);
}
});
}
}
答案 0 :(得分:31)
在你的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
}
};
答案 1 :(得分:3)
设置文本时,您不在UI线程上。如果要处理UI项目,则需要在UI上。在UI线程上创建一个消息处理程序,将消息发布到它,并从UI线程上的处理程序调用setText。
答案 2 :(得分:1)
你可以在线程中执行此操作:
msgToServer.post(new Runnable() {
public void run() {
msgToServer.setText("your text here");
}
}
答案 3 :(得分:0)
您的问题是,您只能在UI线程上进行某些交互。这是其中之一。
看起来您可能想要使用AsyncTask
http://developer.android.com/reference/android/os/AsyncTask.html
基本上你可以让你的Runnable成为AsyncTask,并在onProgressUpdate中执行setText,它会在UIThread上运行。
答案 4 :(得分:0)
如果您想使用 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();