我正在编写一个基于IRC的聊天应用程序。该应用程序在开始时运行良好但是当我们开始使用它并且开始有大量消息传入时,应用程序显着减慢并且最终ANR弹出。这发生在大厅(群聊)视图中,用户可以看到在线用户列表,私人消息列表等。我已经尝试了一切,如eclipse内存分析器,DDMS CPU分析。我找不到实际的问题。这让我疯狂。我不知道问题是什么。我正在使用一个服务,它会在收到消息时发送监听消息并发送广播消息。在服务中,我正在启动一个打开套接字和连续循环的新线程。一旦应用程序开始滞后,我会收到很多GC_CONCURRENT消息:
01-30 20:28:39.240: D/dalvikvm(14593): GC_CONCURRENT freed 1321K, 33% free 11755K/17415K, paused 110ms+41ms, total 292ms
01-30 20:28:39.240: D/dalvikvm(14593): WAIT_FOR_CONCURRENT_GC blocked 182ms
01-30 20:28:48.780: D/dalvikvm(14593): GC_CONCURRENT freed 1784K, 33% free 11813K/17415K, paused 116ms+25ms, total 243ms
01-30 20:28:48.780: D/dalvikvm(14593): WAIT_FOR_CONCURRENT_GC blocked 128ms
01-30 20:28:50.420: D/dalvikvm(14593): GC_CONCURRENT freed 1893K, 33% free 11763K/17415K, paused 111ms+11ms, total 169ms
01-30 20:28:50.420: D/dalvikvm(14593): WAIT_FOR_CONCURRENT_GC blocked 59ms
我不知道我的问题是什么。我试图弄清楚自过去5天以来没有进展。
以下是我的服务代码:
public class ChatService extends Service{
public static final String BROADCAST_ACTION =
"com.webbisswift.NepalMessenger.Broadcast";
public static final String BROADCAST_CHANMSG=
"com.webbisswift.NepalMessenger.BroadcastChannelMessage";
public static final String BROADCAST_PMMSG=
"com.webbisswift.NepalMessenger.BroadcastPrivateMessage";
public static final String BROADCAST_USERJOIN=
"com.webbisswift.NepalMessenger.BroadcastUserJoin";
public static final String BROADCAST_USERLEAVE=
"com.webbisswift.NepalMessenger.BroadcastUserLeave";
public static final String BROADCAST_USERLISTARRIVE=
"com.webbisswift.NepalMessenger.BroadcastUserListArrive";
public static final String BROADCAST_ALERT=
"com.webbisswift.NepalMessenger.BroadcastAlert";
public static final String BROADCAST_KICKED=
"com.webbisswift.NepalMessenger.BroadcastUserKicked";
public static final String BROADCAST_NICK_CHANGED=
"com.webbisswift.NepalMessenger.BroadcastNickChanged";
public static final String CACHE_HEAD="com.webbisswift.NepalMessenger.PMCache.";
public static final int MASTER_NOTIF=111;
private IRCHandler irc;
private String quitMsg="Download Chat Chautari for Android.";
private boolean bound;
private Context mContext=this;
public ArrayList<String> pmList=new ArrayList<String>();
private RoomDatabase room_db;
private PMDatabase pm_db;
public String getCurNick(){
if(irc!=null)
return irc.nick;
else{
Log.d("IRC","IRC NULL");
return null;
}
}
public ArrayList<String> getUsers(){
return irc.userMap;
}
public String getCurChannel(){
return irc.channel;
}
public void putToPMList(String nick){
if(!pmList.contains(nick))
pmList.add(nick);
}
private void showPMNotification(Message message){
NotificationCompat.Builder builder=new NotificationCompat.Builder(this)
.setSmallIcon(R.drawable.ic_launcher)
.setContentTitle("PM From: "+message.getFrom())
.setContentText(message.getPayload());
Uri soundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
builder.setSound(soundUri);
Intent intent = new Intent(this, PMActivity.class);
Log.d("NOTIF_FROM",message.getFrom());
intent.putExtra("PEER", message.getFrom());
PendingIntent pIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
builder.setContentIntent(pIntent);
NotificationManager mNotificationManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
// mId allows you to update the notification later on.
mNotificationManager.notify(110,builder.build());
}
public void disconnectIRC(){
if(irc!=null)
irc.closeConnection();
}
private Notification getMasterNotification(String channel,String nick){
NotificationCompat.Builder builder=new NotificationCompat.Builder(this)
.setSmallIcon(R.drawable.ic_launcher)
.setContentTitle(getText(R.string.app_name))
.setContentText("Connecting to "+channel+" as "+nick);
Intent intent = new Intent(this, RoomActivity.class);
PendingIntent pIntent = PendingIntent.getActivity(this, 0, intent, 0);
builder.setContentIntent(pIntent);
Notification notif=builder.build();
notif.flags |= Notification.FLAG_ONGOING_EVENT | Notification.FLAG_FOREGROUND_SERVICE | Notification.FLAG_NO_CLEAR;
return notif;
}
private void setMasterNotification(String message){
NotificationCompat.Builder builder=new NotificationCompat.Builder(this)
.setSmallIcon(R.drawable.ic_launcher)
.setContentTitle(getText(R.string.app_name))
.setContentText(message);
Intent intent = new Intent(this, RoomActivity.class);
PendingIntent pIntent = PendingIntent.getActivity(this, 0, intent, 0);
builder.setContentIntent(pIntent);
Notification notif=builder.build();
notif.flags |= Notification.FLAG_ONGOING_EVENT | Notification.FLAG_FOREGROUND_SERVICE | Notification.FLAG_NO_CLEAR;
NotificationManager mNotificationManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
// mId allows you to update the notification later on.
mNotificationManager.notify(MASTER_NOTIF,builder.build());
}
public class LocalBinder extends Binder {
ChatService getService() {
return ChatService.this;
}
}
@Override
public IBinder onBind(Intent intent) {
bound = true;
return mBinder;
}
private final IBinder mBinder = new LocalBinder();
public boolean send(Message message){
if(irc.sendMessage(message)){
if(message.getTo().contentEquals(getCurChannel())){
//add sent msg to roomdb
room_db.addMessage(message);
}else{
pm_db.addMessage(message.getFrom()+": "+message.getPayload(), message.getTo());
}
return true;
}
else {
return false;
}
}
public boolean sendCommand(String command){
return irc.sendCommand(command);
}
public void setQuitMsg(String msg){
this.quitMsg=msg;
}
public void changeNick(String nick){
irc.changeNick(nick);
}
public void registerNick(String pass,String email){
irc.registerNick(pass, email);
}
public boolean quit(){
return irc.quit(quitMsg);
}
@Override
public boolean onUnbind(Intent intent) {
bound = false;
return true; // ensures onRebind is called
}
@Override
public void onRebind(Intent intent) {
bound = true;
}
public void reJoin(){
if( irc.join())
setMasterNotification("Connected to "+irc.channel);
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
//now start communication thread
final String nick=intent.getStringExtra("NICK");
final String channel=intent.getStringExtra("CHANNEL");
final String password=intent.getStringExtra("PASSWORD");
room_db=new RoomDatabase(mContext);
pm_db=new PMDatabase(mContext);
pm_db.open();
room_db.open();
//check if internet is there or not
if(!isOnline()){
//failure
Log.d("SERVICE","LOGIN FAIL");
sendLoginResponse(IRCHandler.LOGIN_FAIL);
setMasterNotification("No internet connection.");
}
setMasterNotification("Connecting..");
Thread t=new Thread(new Runnable(){
@Override
public void run() {
try {
irc=new IRCHandler("irc.chatsansar.com",nick,channel,6667);
int response=irc.login(password);
Log.d("SERVICE","LOGIN CALLED");
if(response==IRCHandler.LOGIN_SUCCESS){
//login successful reply this msg to the GUI
Log.d("SERVICE","LOGIN SUCCESS");
sendLoginResponse(IRCHandler.LOGIN_SUCCESS);
setMasterNotification("Connected, joining channel..");
if(irc.join()){
sendJoinResponse(IRCHandler.JOIN_SUCCESS);
//we need to use some listeners
setMasterNotification("Joined channel: "+channel);
irc.setChannelListener(new ChannelListener(){
@Override
public void onNewMessage(Message message) {
// When a new message comes, send a message broadcast
if(bound)
sendLastMessage(message);
room_db.addMessage(message);
}
@Override
public void onAlert(String alert) {
// TODO Auto-generated method stub
sendAlert(alert);
}
@Override
public void onUserLeave(String nick,String message) {
// TODO Auto-generated method stub
sendLeaveMessage(nick,message);
}
@Override
public void onUserJoin(String user) {
// TODO Auto-generated method stub
sendJoinMessage(user);
}
@Override
public void onUserListArrive() {
// TODO Auto-generated method stub
sendULArrive();
}
@Override
public void onKicked(String msg) {
// TODO Auto-generated method stub
setMasterNotification("Kicked from channel.");
sendKickedNotice(msg);
}
@Override
public void onNickChanged() {
// TODO Auto-generated method stub
resetNick();
}});
irc.setPMListener(new PMListener(){
@Override
public void onNewMessage(Message message) {
// TODO Auto-generated method stub
if(!pmList.contains(message.getFrom()))
pmList.add(message.getFrom());
if(bound){
sendPM(message);
}else{
showPMNotification(message);
}
pm_db.addMessage(message.getFrom()+": "+message.getPayload(),message.getFrom());
}
@Override
public void onKicked(String msg) {
// TODO Auto-generated method stub
sendKickedNotice(msg);
}
});
irc.readServer();
}
else {
sendJoinResponse(IRCHandler.JOIN_SUCCESS);
irc.closeConnection();
}
}else if(response==IRCHandler.NICK_TAKEN){
//nick already taken.
Log.d("SERVICE","NICK TAKEN");
sendLoginResponse(IRCHandler.NICK_TAKEN);
}else if(response==IRCHandler.INVALID_NICK){
//nick already taken.
Log.d("SERVICE","INVALID NICK");
sendLoginResponse(IRCHandler.INVALID_NICK);
}else{
//failure
Log.d("SERVICE","LOGIN FAIL");
sendLoginResponse(IRCHandler.LOGIN_FAIL);
}
room_db.close();
pm_db.close();
irc.closeConnection();
}catch(Exception e){
e.printStackTrace();
room_db.close();
pm_db.close();
Log.d("SERVICE","IRC DISCONNECTED");
sendLoginResponse(IRCHandler.LOGIN_FAIL);
setMasterNotification("Disconnected from server.");
stopSelf();
}
}
});
t.start();
startForeground(MASTER_NOTIF, getMasterNotification(channel,nick));
return Service.START_REDELIVER_INTENT;
}
protected void sendLeaveMessage(String nick, String message) {
// TODO Auto-generated method stub
Intent localIntent=new Intent(ChatService.BROADCAST_USERLEAVE);
localIntent.putExtra("NICK",nick);
localIntent.putExtra("MESSAGE", message);
sendBroadcast(localIntent);
}
private void sendJoinResponse(int joinSuccess) {
// TODO Auto-generated method stub
Intent localIntent =
new Intent(BROADCAST_ACTION);
localIntent.putExtra("JOIN",joinSuccess);
sendBroadcast(localIntent);
}
private void sendLoginResponse(int response){
Intent localIntent =
new Intent(BROADCAST_ACTION);
localIntent.putExtra("LOGIN",response);
sendBroadcast(localIntent);
}
private void sendLastMessage(Message msg){
Intent localIntent=new Intent(ChatService.BROADCAST_CHANMSG);
localIntent.putExtra("MESSAGE", msg.getPayload());
localIntent.putExtra("FROM", msg.getFrom());
localIntent.putExtra("MESSAGE", msg.getPayload());
sendBroadcast(localIntent);
}
private void sendJoinMessage(String user){
Intent localIntent=new Intent(ChatService.BROADCAST_USERJOIN);
localIntent.putExtra("NICK",user);
sendBroadcast(localIntent);
}
private void sendULArrive(){
Intent localIntent=new Intent(ChatService.BROADCAST_USERLISTARRIVE);
sendBroadcast(localIntent);
}
private void sendPM(Message msg){
Intent localIntent=new Intent(ChatService.BROADCAST_PMMSG);
localIntent.putExtra("MESSAGE", msg.getPayload());
localIntent.putExtra("FROM", msg.getFrom());
sendBroadcast(localIntent);
}
private void sendAlert(String alert){
Intent localIntent=new Intent(ChatService.BROADCAST_ALERT);
localIntent.putExtra("MESSAGE", alert);
sendBroadcast(localIntent);
}
private void sendKickedNotice(String msg){
Intent localIntent=new Intent(ChatService.BROADCAST_KICKED);
localIntent.putExtra("MESSAGE",msg );
sendBroadcast(localIntent);
}
private void resetNick(){
Intent localIntent=new Intent(ChatService.BROADCAST_NICK_CHANGED);
sendBroadcast(localIntent);
}
public boolean hasIRC() {
// TODO Auto-generated method stub
if(irc==null)
return false;
else return true;
}
private boolean isOnline() {
ConnectivityManager cm =
(ConnectivityManager) this.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo netInfo = cm.getActiveNetworkInfo();
if (netInfo != null && netInfo.isConnectedOrConnecting()) {
return true;
}
return false;
}
public void delDB() {
Log.d("DATABASE","CLEARED");
room_db.drop();
pm_db.drop();
}
}