Android 安卓系统:;带未捕获异常的线程退出(组=0x4001d800)";

Android 安卓系统:;带未捕获异常的线程退出(组=0x4001d800)";,android,Android,我正在做一个在eclipse上运行的android(客户端)和pc(java_服务器)之间的局域网聊天应用程序。问题是android非常不稳定,而且经常崩溃,但是,它在我的java版本的客户端和服务器上运行得非常好。请帮忙 private Handler myHandler = new Handler(){ @Override public void handleMessage(Message msg){ String str= (String) msg.obj

我正在做一个在eclipse上运行的android(客户端)和pc(java_服务器)之间的局域网聊天应用程序。问题是android非常不稳定,而且经常崩溃,但是,它在我的java版本的客户端和服务器上运行得非常好。请帮忙

private Handler myHandler = new Handler(){
    @Override
    public void handleMessage(Message msg){
        String  str= (String) msg.obj;
        if(msg.what==1){
            msgArrayAdapter.add(str);
        }
    }
};`
这是我的代码:

package android.client;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.PriorityQueue;
import java.util.Queue;

import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.ArrayAdapter;
import android.widget.Button;
 import android.widget.EditText;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;
private Handler myHandler = new Handler(){
    @Override
    public void handleMessage(Message msg){
        String  str= (String) msg.obj;
        if(msg.what==1){
            msgArrayAdapter.add(str);
        }
    }
};`
公共类聊天室客户端扩展活动实现可运行{

private Socket socket = null;
//private Thread thread = null;
private DataOutputStream requestOut;
private int clientID;
private String playerName;
private DataInputStream requestIn;
private EditText text;
private ListView msgView;
private ArrayAdapter<String> msgArrayAdapter;

/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);
    try {
        socket = new Socket("192.168.2.2", 5558);
        Toast.makeText(this,
                "Connected to " + this.socket.getInetAddress(),
                Toast.LENGTH_LONG + 10).show();
        this.playerName = "wei";
        this.clientID = socket.getLocalPort();
        requestOut = new DataOutputStream(socket.getOutputStream());
        requestIn = new DataInputStream(socket.getInputStream());
        text = (EditText) findViewById(R.id.editText1);// black textfield
        msgArrayAdapter = new ArrayAdapter<String>(this, R.layout.message);
        msgView = (ListView) findViewById(R.id.in);
        msgView.setAdapter(this.msgArrayAdapter);
        new Thread(this).start();
    } catch (UnknownHostException uke) {
        Toast.makeText(this, "Host unknown:" + uke.getMessage(),
                Toast.LENGTH_LONG).show();
    } catch (IOException ioe) {
        Toast.makeText(this, "Unexpected exception: " + ioe.getMessage(),
                Toast.LENGTH_LONG).show();
    }
}


// This method is called at button click because we assigned the name to the
// "On Click property" of the button
public void myClickHandler(View v) {
    Toast.makeText(this, "sending", Toast.LENGTH_LONG/2).show();
    TextView view = (TextView) findViewById(R.id.editText1);
    String message = view.getText().toString();
    text.setText("");
    Packet p;
    if (message.startsWith("#")) {
        p = new Packet(playerName, 1, clientID,message.substring(1,    message.length()));
    } 
    else 
        p = new Packet(playerName, -1, clientID,message);
    try {
        this.requestOut.writeUTF(p.convertToSendFormat());
        requestOut.flush();
        } catch (IOException e) {
            e.printStackTrace();
        }
    msgArrayAdapter.add("Me: <" + message + ">");

}

public void run() {
    while (true) {
        String r;
        try {
            r = this.requestIn.readUTF();
            if (r != null) {
                Packet p = convert(r);
                if (p != null)
                    handle(p);
            }
        } catch (IOException ioe) {
            System.exit(0);
        }
    }
}
private synchronized Packet convert(String n) {
    String data = "";
    String[] p = n.split(" ", 4);
    if (p.length < 4)
        return null;
    data = p[3];
    return new Packet(p[0], Integer.parseInt(p[1]), Integer.parseInt(p[2]),
            data);
}
public synchronized void handle(Packet re) {
    if (re.getChannelID() == clientID){
        msgArrayAdapter.add("Me" + re.toString());}
    else{
        msgArrayAdapter.add(re.getSenderName() + re.toString());
        }
    }
private Handler myHandler = new Handler(){
    @Override
    public void handleMessage(Message msg){
        String  str= (String) msg.obj;
        if(msg.what==1){
            msgArrayAdapter.add(str);
        }
    }
};`
下面是日志:

  10-12 12:54:22.763: DEBUG/AndroidRuntime(360): >>>>>>>>>>>>>> AndroidRuntime START <<<<<<<<<<<<<<
10-12 12:54:22.763: DEBUG/AndroidRuntime(360): CheckJNI is ON
10-12 12:54:22.895: DEBUG/AndroidRuntime(360): --- registering native functions ---
10-12 12:54:23.513: INFO/ActivityManager(59): Force stopping package android.client uid=10033
10-12 12:54:23.513: INFO/ActivityManager(59): Starting activity: Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10000000 cmp=android.client/.Chat_client }
10-12 12:54:23.633: DEBUG/AndroidRuntime(360): Shutting down VM
10-12 12:54:23.645: INFO/ActivityManager(59): Start proc android.client for activity android.client/.Chat_client: pid=366 uid=10033 gids={3003}
10-12 12:54:23.664: DEBUG/jdwp(360): Got wake-up signal, bailing out of select
10-12 12:54:23.664: DEBUG/dalvikvm(360): Debugger has detached; object registry had 1 entries
10-12 12:54:24.024: WARN/ActivityThread(366): Application android.client is waiting for the debugger on port 8100...
10-12 12:54:24.044: INFO/System.out(366): Sending WAIT chunk
10-12 12:54:24.054: INFO/dalvikvm(366): Debugger is active
10-12 12:54:24.244: INFO/System.out(366): Debugger has connected
10-12 12:54:24.244: INFO/System.out(366): waiting for debugger to settle...
10-12 12:54:24.444: INFO/System.out(366): waiting for debugger to settle...
10-12 12:54:24.644: INFO/System.out(366): waiting for debugger to settle...
10-12 12:54:24.843: INFO/System.out(366): waiting for debugger to settle...
10-12 12:54:25.053: INFO/System.out(366): waiting for debugger to settle...
10-12 12:54:25.254: INFO/System.out(366): waiting for debugger to settle...
10-12 12:54:25.454: INFO/System.out(366): waiting for debugger to settle...
10-12 12:54:25.654: INFO/System.out(366): waiting for debugger to settle...
10-12 12:54:25.866: INFO/System.out(366): waiting for debugger to settle...
10-12 12:54:26.075: INFO/System.out(366): waiting for debugger to settle...
10-12 12:54:26.284: INFO/System.out(366): debugger has settled (1322)
10-12 12:54:27.544: INFO/ActivityManager(59): Displayed activity android.client/.Chat_client: 3912 ms (total 3912 ms)
10-12 12:54:33.313: DEBUG/dalvikvm(124): GC_EXPLICIT freed 642 objects / 35976 bytes in 203ms
10-12 12:54:38.335: DEBUG/dalvikvm(225): GC_EXPLICIT freed 152 objects / 11144 bytes in 177ms
10-12 12:54:43.384: DEBUG/dalvikvm(261): GC_EXPLICIT freed 249 objects / 11840 bytes in 205ms
10-12 12:55:14.583: WARN/KeyCharacterMap(108): No keyboard for id 0
10-12 12:55:14.583: WARN/KeyCharacterMap(108): Using default keymap: /system/usr/keychars/qwerty.kcm.bin
10-12 12:55:37.295: WARN/dalvikvm(366): threadid=7: thread exiting with uncaught exception (group=0x4001d800)
private Handler myHandler = new Handler(){
    @Override
    public void handleMessage(Message msg){
        String  str= (String) msg.obj;
        if(msg.what==1){
            msgArrayAdapter.add(str);
        }
    }
};`

10-12 12:54:22.763:DEBUG/AndroidRuntime(360):>>>>>>>>>>>>>>>>>>>>>>>>>>AndroidRuntime START这是一个干净的方法(我不知道这是否解决了您的实际问题)。但无论如何,从另一个线程更新适配器阵列都不是一个好主意。如果您的设备正在旋转,您将使用已运行的线程创建另一个线程。并且在更改阵列(消息)时,不要忘记通过调用
msgArrayAdapter.notifyDataSetChanged()
刷新列表.这是蓝图和想法

private Handler myHandler = new Handler(){
    @Override
    public void handleMessage(Message msg){
        String  str= (String) msg.obj;
        if(msg.what==1){
            msgArrayAdapter.add(str);
        }
    }
};`
您的活动。它将以正确的方式对配置更改和实际销毁做出反应:

private MessagePollThread thread;

public void onCreate(Bundle b) {
    super.onCreate(b);

    thread = (MessagePollThread) getLastNonConfigurationInstance();

    if (thread == null) {
        // activity runs for first time - create thread
        thread = new MessagePollThread();
        thread.activity = this;
        thread.start();
    } else {
        // just update the thread with the new activity - it's started already
        thread.activity = this;
    }
}

public Object onRetainNonConfigurationInstance() {
    // retain the thread for configuration changes e.g. orientation change (see onCreate)
    return thread;

    // you could also retain your old received messages here
    // just return new Object [] {thread, messageArray} and handle that in onCreate
}

public void onDestroy() {
    super.onDestroy();

    if (isFinishing()) {
        // activity is about to destroy itself
        // shutdown the running thread
        thread.run = false;
        thread.interrupt(); // break the sleep
    }
}
private Handler myHandler = new Handler(){
    @Override
    public void handleMessage(Message msg){
        String  str= (String) msg.obj;
        if(msg.what==1){
            msgArrayAdapter.add(str);
        }
    }
};`
处理请求的实际线程(作为活动的内部静态类):

private Handler myHandler = new Handler(){
    @Override
    public void handleMessage(Message msg){
        String  str= (String) msg.obj;
        if(msg.what==1){
            msgArrayAdapter.add(str);
        }
    }
};`

这是一个干净的方法(我不知道这是否解决了你的实际问题)。但无论如何,从另一个线程更新适配器阵列都不是一个好主意。如果您的设备正在旋转,您将使用已运行的线程创建另一个线程。并且在更改阵列(消息)时,不要忘记通过调用
msgArrayAdapter.notifyDataSetChanged()
刷新列表.这是蓝图和想法

private Handler myHandler = new Handler(){
    @Override
    public void handleMessage(Message msg){
        String  str= (String) msg.obj;
        if(msg.what==1){
            msgArrayAdapter.add(str);
        }
    }
};`
您的活动。它将以正确的方式对配置更改和实际销毁做出反应:

private MessagePollThread thread;

public void onCreate(Bundle b) {
    super.onCreate(b);

    thread = (MessagePollThread) getLastNonConfigurationInstance();

    if (thread == null) {
        // activity runs for first time - create thread
        thread = new MessagePollThread();
        thread.activity = this;
        thread.start();
    } else {
        // just update the thread with the new activity - it's started already
        thread.activity = this;
    }
}

public Object onRetainNonConfigurationInstance() {
    // retain the thread for configuration changes e.g. orientation change (see onCreate)
    return thread;

    // you could also retain your old received messages here
    // just return new Object [] {thread, messageArray} and handle that in onCreate
}

public void onDestroy() {
    super.onDestroy();

    if (isFinishing()) {
        // activity is about to destroy itself
        // shutdown the running thread
        thread.run = false;
        thread.interrupt(); // break the sleep
    }
}
private Handler myHandler = new Handler(){
    @Override
    public void handleMessage(Message msg){
        String  str= (String) msg.obj;
        if(msg.what==1){
            msgArrayAdapter.add(str);
        }
    }
};`
处理请求的实际线程(作为活动的内部静态类):

private Handler myHandler = new Handler(){
    @Override
    public void handleMessage(Message msg){
        String  str= (String) msg.obj;
        if(msg.what==1){
            msgArrayAdapter.add(str);
        }
    }
};`

我通过添加一个处理程序方法解决了这个问题:

private Handler myHandler = new Handler(){
    @Override
    public void handleMessage(Message msg){
        String  str= (String) msg.obj;
        if(msg.what==1){
            msgArrayAdapter.add(str);
        }
    }
};`

当然,我不知道为什么会这样,但它确实有效。哈哈,再次感谢@Knickedi的帮助。我通过添加一个handler方法解决了这个问题:

private Handler myHandler = new Handler(){
    @Override
    public void handleMessage(Message msg){
        String  str= (String) msg.obj;
        if(msg.what==1){
            msgArrayAdapter.add(str);
        }
    }
};`

当然,我不知道为什么会这样,但它只是起作用。哈哈,再次感谢@Knickedi的帮助。

有没有可能你的应用程序在设备旋转时/之后崩溃?不确定,因为我使用的是虚拟设备(模拟器)你的应用程序是否可能在设备旋转时/旋转后崩溃?不确定,因为我使用的虚拟设备(模拟器)仍然存在问题(随机),无论如何,谢谢你的帮助。如果我不使用ArrayAdapter,这个问题会解决吗?或者有一种方法不使用线程来解决这个问题?你使用什么都不重要。强烈建议使用线程来完成网络任务,在这种情况下甚至是必要的。你只需确保在UI线程上修改与UI相关的数据。我很抱歉,我现在真的说不出是什么导致了您的异常…仍然存在问题(随机),无论如何,谢谢你的帮助。如果我不使用ArrayAdapter,这个问题会解决吗?或者有一种方法不使用线程来解决这个问题?你使用什么都不重要。强烈建议使用线程来完成网络任务,在这种情况下甚至是必要的。你只需确保在UI线程上修改与UI相关的数据。我很抱歉,我现在真的说不出是什么导致了你的异常。。。
private Handler myHandler = new Handler(){
    @Override
    public void handleMessage(Message msg){
        String  str= (String) msg.obj;
        if(msg.what==1){
            msgArrayAdapter.add(str);
        }
    }
};`