06-13 17:29:30.750: W/dalvikvm(6257): threadid=13: thread exiting with uncaught exception (group=0xb1af0ba8)
06-13 17:29:30.780: E/AndroidRuntime(6257): FATAL EXCEPTION: Thread-251
06-13 17:29:30.780: E/AndroidRuntime(6257): Process: me.l0lkj.birthdaytimer, PID: 6257
06-13 17:29:30.780: E/AndroidRuntime(6257): android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
06-13 17:29:30.780: E/AndroidRuntime(6257): at android.view.ViewRootImpl.checkThread(ViewRootImpl.java:6094)
06-13 17:29:30.780: E/AndroidRuntime(6257): at android.view.ViewRootImpl.invalidateChildInParent(ViewRootImpl.java:857)
06-13 17:29:30.780: E/AndroidRuntime(6257): at android.view.ViewGroup.invalidateChild(ViewGroup.java:4320)
06-13 17:29:30.780: E/AndroidRuntime(6257): at android.view.View.invalidate(View.java:10935)
06-13 17:29:30.780: E/AndroidRuntime(6257): at android.view.View.invalidate(View.java:10890)
06-13 17:29:30.780: E/AndroidRuntime(6257): at android.widget.TextView.updateAfterEdit(TextView.java:7430)
06-13 17:29:30.780: E/AndroidRuntime(6257): at android.widget.TextView.handleTextChanged(TextView.java:7453)
06-13 17:29:30.780: E/AndroidRuntime(6257): at android.widget.TextView$ChangeWatcher.onTextChanged(TextView.java:9183)
06-13 17:29:30.780: E/AndroidRuntime(6257): at android.text.SpannableStringBuilder.sendTextChanged(SpannableStringBuilder.java:962)
06-13 17:29:30.780: E/AndroidRuntime(6257): at android.text.SpannableStringBuilder.replace(SpannableStringBuilder.java:496)
06-13 17:29:30.780: E/AndroidRuntime(6257): at android.text.SpannableStringBuilder.append(SpannableStringBuilder.java:253)
06-13 17:29:30.780: E/AndroidRuntime(6257): at android.text.SpannableStringBuilder.append(SpannableStringBuilder.java:30)
06-13 17:29:30.780: E/AndroidRuntime(6257): at android.widget.TextView.append(TextView.java:3409)
06-13 17:29:30.780: E/AndroidRuntime(6257): at android.widget.TextView.append(TextView.java:3396)
06-13 17:29:30.780: E/AndroidRuntime(6257): at me.l0lkj.birthdaytimer.Screen2.appendTextAndScroll(Screen2.java:180)
06-13 17:29:30.780: E/AndroidRuntime(6257): at me.l0lkj.birthdaytimer.Screen2.access$1(Screen2.java:177)
06-13 17:29:30.780: E/AndroidRuntime(6257): at me.l0lkj.birthdaytimer.Screen2$ListenFromServer.run(Screen2.java:273)
06-13 17:29:58.330: I/Process(6257): Sending signal. PID: 6257 SIG: 9
06-13 17:33:57.960: D/dalvikvm(6315): GC_FOR_ALLOC freed 57K, 9% free 3567K/3920K, paused 137ms, total 138ms
06-13 17:33:58.590: D/(6315): HostConnection::get() New Host Connection established 0xb91170e0, tid 6315
06-13 17:34:10.310: E/Første skjerm(6315): 10.0.0.59.1500.Anonym.123123
06-13 17:34:11.460: D/dalvikvm(6315): GC_FOR_ALLOC freed 19K, 8% free 3894K/4200K, paused 23ms, total 26ms
06-13 17:34:11.480: I/dalvikvm-heap(6315): Grow heap (frag case) to 6.498MB for 2536936-byte allocation
06-13 17:34:11.510: D/dalvikvm(6315): GC_FOR_ALLOC freed 1K, 5% free 6370K/6680K, paused 31ms, total 31ms
06-13 17:34:11.690: E/Andre skjerm(6315): 10.0.0.59.1500.Anonym.123123
我只是开始编码,目前正在使用Android的聊天客户端,但遇到了以下问题:
ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
我四处搜寻,但似乎找不到任何能解决此问题的东西。短期我想要的是:
一个很好的解释,这个问题是什么以及如何解决它。为什么会发生等等
更正我的代码或帮助我找到解决方案。我阅读了有关哪些类可以接受和不能接受的内容的一些明显了解,但是我没有找到好的解决方案。
我的代码有点凌乱,对此感到抱歉(我仍然是菜鸟,请记住:))
package me.l0lkj.birthdaytimer;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;
import java.util.ArrayList;
import me.l0lkj.birthdaytimer.userlisthandler.UserInfo;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.text.Layout;
import android.text.method.ScrollingMovementMethod;
import android.util.Log;
import android.view.KeyEvent;
import android.view.View;
import android.view.inputmethod.EditorInfo;
import android.widget.Button;
import android.widget.ScrollView;
import android.widget.TextView;
import android.widget.TextView.OnEditorActionListener;
public class Screen2 extends Activity {
ArrayList<UserInfo> lastPlayerRegrex = new ArrayList<UserInfo>();
boolean running = false;
ScrollView chat_ScrollView;
TextView chat_text_chat;
TextView editText1;
String server;
int port;
String brukernavn;
String passord;
private ObjectInputStream sInput;
private ObjectOutputStream sOutput;
private Socket socket;
@Override
public void onCreate(Bundle savedInstanceState) {
running = true;
super.onCreate(savedInstanceState);
setContentView(R.layout.screen2);
Button btnSend = (Button) findViewById(R.id.btnSend);
btnSend.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
sendLine();
}
});
Button btnClose = (Button) findViewById(R.id.btnClose);
btnClose.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
appendTextAndScroll("Forlater nå chatten!!");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
running = false;
disconnect();
}
});
Button btnList = (Button) findViewById(R.id.btnList);
btnList.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
//String test = "NAME:l0lkj;IP:10.0.0.39;SINCE:123422,NAME:asdasd;IP:10.0.0.234;SINCE:345678,NAME:ihkjhg;IP:10.04.6.7;SINCE:078273549234";
sendMessage(new Message(Message.LIST_USERS, ""));
//ArrayList<UserInfo> users = Format(test);
/*
* Denne metoden skal sende inn en Message med syntaksen:
*
* new Message(4, "");
*
*
*
*/
/*
for(UserInfo user : users){
long millis = user.getTid();
int seconds = (int) (millis / 1000) % 60 ;
int minutes = (int) ((millis / (1000*60)) % 60);
int hours = (int) ((millis / (1000*60*60)) % 24);
String userdata = user.getName() + " IP:" + user.getIp() + " \n Tid online: " + hours + " timer, " + minutes + " minutter og " + seconds + " sekunder.";
appendTextAndScroll(userdata);
}*/
}
});
editText1 = (TextView) this.findViewById(R.id.editText1);
editText1.setOnEditorActionListener(new OnEditorActionListener() {
@Override
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
boolean handled = false;
if (actionId == EditorInfo.IME_ACTION_SEND) {
sendLine();
handled = true;
}
return handled;
}
});
chat_text_chat = (TextView) this.findViewById(R.id.chat_text_chat);
chat_text_chat.setMovementMethod(new ScrollingMovementMethod());
Intent i = getIntent();
server = i.getStringExtra("server");
port = Integer.parseInt(i.getStringExtra("port"));
brukernavn = i.getStringExtra("brukernavn");
passord = i.getStringExtra("passord");
Log.e("Andre skjerm", server + "." + port + "." + brukernavn + "." + passord);
appendTextAndScroll("");
this.start();
}
private void disconnect() {
try {
if(sInput != null) sInput.close();
}
catch(Exception e) {}
try {
if(sOutput != null) sOutput.close();
}
catch(Exception e) {}
try{
if(socket != null) socket.close();
}
catch(Exception e) {}
finish();
}
@SuppressWarnings("unused")
private void startConnection(String address, int port){
}
private void broadcastText(String text){
//appendTextAndScroll(text);
this.sendMessage(new Message(Message.MELDING, text));
//sende til serveren
}
private void sendMessage(Message msg){
try {
sOutput.writeObject(msg);
}
catch(IOException e) {
appendTextAndScroll("Exception writing to server: " + e);
}
}
private void appendTextAndScroll(String text) {
if(text.length() >= 1){
if(chat_text_chat != null){
chat_text_chat.append(text + "\n");
final Layout layout = chat_text_chat.getLayout();
if(layout != null){
int scrollDelta = layout.getLineBottom(chat_text_chat.getLineCount() - 1) - chat_text_chat.getScrollY() - chat_text_chat.getHeight();
if(scrollDelta > 0){
chat_text_chat.scrollBy(0, scrollDelta);
}
}
}
}
}
private void sendLine(){
String text = editText1.getText().toString();
editText1.setText("");
broadcastText(text);
}
public ArrayList<UserInfo> Format(String rawFromServer){
ArrayList<UserInfo> userObjects = new ArrayList<UserInfo>();
String[] users = rawFromServer.split(",");
for(String user : users){
String name = null;
String ip = null;
long since = 0;
String[] keys = user.split(";");
for(String key : keys){
String[] keyAndAns = key.split(":");
if(keyAndAns[0].equals("NAME")){
name = keyAndAns[1];
}
if(keyAndAns[0].equals("IP")){
ip = keyAndAns[1];
}
if(keyAndAns[0].equals("SINCE")){
since = Long.parseLong(keyAndAns[1]);
}
}
userObjects.add(new UserInfo(name, ip, since));
}
return userObjects;
}
public boolean start() {
try {
socket = new Socket(server, port);
}
catch(Exception ec) {
appendTextAndScroll("Feil under oppkobling til serveren:" + ec);
return false;
}
String msg = "Kobling godtatt fra " + socket.getInetAddress() + ":" + socket.getPort();
appendTextAndScroll(msg);
try
{
sInput = new ObjectInputStream(socket.getInputStream());
sOutput = new ObjectOutputStream(socket.getOutputStream());
}
catch (IOException eIO) {
appendTextAndScroll("Unntak ved ny Input/output strøm: " + eIO);
return false;
}
new ListenFromServer().start();
try {
sOutput.writeObject((brukernavn + ":" + passord));
} catch (IOException e) {
e.printStackTrace();
}
return true;
}
class ListenFromServer extends Thread {
public void run() {
while(true) {
try {
String msg = (String) sInput.readObject();
appendTextAndScroll(msg);
}
catch(IOException e) {
appendTextAndScroll("Serveren har stengt koblingen: " + e);
break;
}
catch(ClassNotFoundException e2) {}
}
}
}
}
谢谢你的答案;
最好的问候亚历山大
最佳答案
由于尝试从后台线程更新视图,因此出现CalledFromWrongThreadException
错误。那是不允许的。
在这种情况下,最简单的更改可能是修改appendTextAndScroll()
本身,以确保它在UI线程中运行。
private void appendTextAndScroll(String text)
{
runOnUiThread(new Runnable()
{
public void run()
{
if(text.length() >= 1){
if(chat_text_chat != null){
chat_text_chat.append(text + "\n");
final Layout layout = chat_text_chat.getLayout();
if(layout != null){
int scrollDelta = layout.getLineBottom(chat_text_chat.getLineCount() - 1) - chat_text_chat.getScrollY() - chat_text_chat.getHeight();
if(scrollDelta > 0){
chat_text_chat.scrollBy(0, scrollDelta);
}
}
}
}
}
});
}