Android编码:ViewRootImpl $ CalledFromWrongThreadException。 [菜鸟]

时间:2014-06-13 21:53:37

标签: java android network-programming

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.

我已经四处寻找,但似乎无法找到解决这个问题的任何东西。我想要的是短期内:

  1. 很好地解释了这个问题是什么以及如何解决这个问题。为什么会发生等。

  2. 更正我的代码或帮我找到解决方法。我读到了哪些类可以访问哪些类有点明显,但我发现没有好的解决方案。

  3. 我的代码有点杂乱,对此感到抱歉(我还是个菜鸟,请记住:))

    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) {}
            }
        }
    }
    
    }
    

    感谢您的回答;

    祝贺亚历山大

1 个答案:

答案 0 :(得分:1)

您因为尝试从后台线程更新视图而导致出现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);
                        }
                    }
                }
            }
        }
    });
}
相关问题