2012-09-05 35 views
5

我一直在使用Android开源服务的例子。我只需要用它来发送通知给用户,但奇怪的是,它分配了大量的内存。我检查了运行服务,它几乎是20MB(如果我设置ACTION_BACKGROUND)或30MB(如果我设置ACTION_FOREGROUND)...服务分配大量内存?

我该怎么做才能减少内存使用量?

我已经阅读this discussion我没有位图或网页流量。

这里是我的服务:

/** 
* This is an example of implementing an application service that can 
* run in the "foreground". It shows how to code this to work well by using 
* the improved Android 2.0 APIs when available and otherwise falling back 
* to the original APIs. Yes: you can take this exact code, compile it 
* against the Android 2.0 SDK, and it will against everything down to 
* Android 1.0. 
*/ 

public class NotificationService extends Service { 

static final String ACTION_FOREGROUND = "com.example.android.apis.FOREGROUND"; 
static final String ACTION_BACKGROUND = "com.example.android.apis.BACKGROUND"; 

private static final Class<?>[] mSetForegroundSignature = new Class[] { 
    boolean.class}; 
private static final Class<?>[] mStartForegroundSignature = new Class[] { 
    int.class, Notification.class}; 
private static final Class<?>[] mStopForegroundSignature = new Class[] { 
    boolean.class}; 

// protected NotificationManager mNM; 

private Method mSetForeground; 
private Method mStartForeground; 
private Method mStopForeground; 
private Object[] mSetForegroundArgs = new Object[1]; 
private Object[] mStartForegroundArgs = new Object[2]; 
private Object[] mStopForegroundArgs = new Object[1]; 

void invokeMethod(Method method, Object[] args) { 
    try { 
     method.invoke(this, args); 
    } catch (InvocationTargetException e) { 
     // Should not happen. 
     Log.w("ApiDemos", "Unable to invoke method", e); 
    } catch (IllegalAccessException e) { 
     // Should not happen. 
     Log.w("ApiDemos", "Unable to invoke method", e); 
    } 
} 

/** 
* This is a wrapper around the new startForeground method, using the older 
* APIs if it is not available. 
*/ 
void startForegroundCompat(int id, Notification notification) { 
    // If we have the new startForeground API, then use it. 
    if (mStartForeground != null) { 
     mStartForegroundArgs[0] = Integer.valueOf(id); 
     mStartForegroundArgs[1] = notification; 
     invokeMethod(mStartForeground, mStartForegroundArgs); 
     return; 
    } 

    // Fall back on the old API. 
    mSetForegroundArgs[0] = Boolean.TRUE; 
    invokeMethod(mSetForeground, mSetForegroundArgs); 
    // mNM.notify(id, notification); 
} 

/** 
* This is a wrapper around the new stopForeground method, using the older 
* APIs if it is not available. 
*/ 
void stopForegroundCompat(int id) { 
    // If we have the new stopForeground API, then use it. 
    if (mStopForeground != null) { 
     mStopForegroundArgs[0] = Boolean.TRUE; 
     invokeMethod(mStopForeground, mStopForegroundArgs); 
     return; 
    } 

    // Fall back on the old API. Note to cancel BEFORE changing the 
    // foreground state, since we could be killed at that point. 
    // mNM.cancel(id); 
    mSetForegroundArgs[0] = Boolean.FALSE; 
    invokeMethod(mSetForeground, mSetForegroundArgs); 
} 

@Override 
public void onCreate() { 
    // mNM = (NotificationManager)getSystemService(NOTIFICATION_SERVICE); 
    try { 
     mStartForeground = getClass().getMethod("startForeground", 
       mStartForegroundSignature); 
     mStopForeground = getClass().getMethod("stopForeground", 
       mStopForegroundSignature); 
     return; 
    } catch (NoSuchMethodException e) { 
     // Running on an older platform. 
     mStartForeground = mStopForeground = null; 
    } 
    try { 
     mSetForeground = getClass().getMethod("setForeground", 
       mSetForegroundSignature); 
    } catch (NoSuchMethodException e) { 
     throw new IllegalStateException(
       "OS doesn't have Service.startForeground OR Service.setForeground!"); 
    } 
} 

@Override 
public void onDestroy() { 
    // Make sure our notification is gone. 
    stopForegroundCompat(1); 
} 

// This is the old onStart method that will be called on the pre-2.0 
// platform. On 2.0 or later we override onStartCommand() so this 
// method will not be called. 
@Override 
public void onStart(Intent intent, int startId) { 
    handleCommand(intent); 
} 

@Override 
public int onStartCommand(Intent intent, int flags, int startId) { 
    handleCommand(intent); 
    // We want this service to continue running until it is explicitly 
    // stopped, so return sticky. 
    return START_STICKY; 
} 

@Override 
public void onRebind(Intent intent) { 
    super.onRebind(intent); 
    handleCommand(intent); 
} 

void handleCommand(Intent intent) { 
    if (intent == null) 
     return; 

    if (ACTION_FOREGROUND.equals(intent.getAction())) { 

     DBHelper db = new DBHelper(this); 

     String lastTime = db.getLastVisitTime(); 
     if(!lastTime.equals("-1")) { 
      new Notifications(this).InviteUser(); 
     } 

     String target = db.getTargetValue(); 
     if(target.equals("")) { 
      new Notifications(this).TargetlessNotification(); 
     } 

     db.close(); 

     /* 
     // In this sample, we'll use the same text for the ticker and the expanded notification 
     CharSequence text = getString(R.string.app_name); 
     CharSequence description = getString(R.string.recall_user); 

     // Set the icon, scrolling text and timestamp 
     Notification notification = new Notification(R.drawable.icon, text, System.currentTimeMillis()); 

     // The PendingIntent to launch our activity if the user selects this notification PendingIntent 
     contentIntent = PendingIntent.getActivity(this, 1, new Intent(this, YKEYarinaSaklaActivity.class), 0); 

     // Set the info for the views that show in the notification panel. 
     notification.setLatestEventInfo(this, text, description, contentIntent); 

     // Set properties of notification 
     notification.flags = Notification.FLAG_INSISTENT | Notification.FLAG_AUTO_CANCEL; 
     notification.defaults |= Notification.DEFAULT_ALL; 

     startForegroundCompat(1, notification); 
     */ 


    } else if (ACTION_BACKGROUND.equals(intent.getAction())) { 
     stopForegroundCompat(1); 
    } 
} 

@Override 
public IBinder onBind(Intent intent) { 
    return null; 
} 
} 

PS:我不知道这是否是相关或没有,但我开始我的应用程序的该服务的onDestroy,所以它会发送通知到用户在特定的时间与AlarmManager。 (所以应该不会被杀死,以免AlarmManager删除我的通知。)

+1

转储HPROF数据和[分析](http://android-developers.blogspot.in/2011/03/memory-analysis-for-android.html) – nandeesh

+0

感谢这真棒教程。我已经检查过了,据我所知没有任何问题。但仍分配如此之多:/ – yahya

+0

你尝试转储hprof并检查哪些对象正在使用内存? – nandeesh

回答

2

我试着simplfy我的服务尽可能我可以,但情况还是一样......然后,我意识到,不知何故,用法的记忆本身就会减少...所以,如果我没有选择,我可以除了那个。

public class NotificationService2 extends Service{ 

private String target, lastTime, notifCheck, notifCheck2; 

@Override 
public void onStart(Intent intent, int startId) { 

    Bundle extras = intent.getExtras(); 
    if(extras != null) { 
     this.lastTime = extras.getString("lastTime"); 
     this.target = extras.getString("target"); 
     this.notifCheck = extras.getString("notifCheck"); 
     this.notifCheck2 = extras.getString("notifCheck2"); 
    } 

    handleCommand(intent); 

    super.onStart(intent, startId); 
} 

@Override 
public int onStartCommand(Intent intent, int flags, int startId) { 

    Bundle extras = intent.getExtras(); 
    if(extras != null) { 
     this.lastTime = extras.getString("lastTime"); 
     this.target = extras.getString("target"); 
     this.notifCheck = extras.getString("notifCheck"); 
     this.notifCheck2 = extras.getString("notifCheck2"); 
    } 

    handleCommand(intent); 

    // We want this service to continue running until it is explicitly 
    // stopped, so return sticky. 
    return START_STICKY; 
} 

@Override 
public IBinder onBind(Intent intent) { 
    handleCommand(intent); 
    return null; 
} 

@Override 
public void onRebind(Intent intent) { 
    super.onRebind(intent); 
    handleCommand(intent); 
} 

void handleCommand(Intent intent) { 
    if (intent == null) 
     return; 

    String lastTime = this.lastTime; 
    String notifCheck = this.notifCheck; 
    String target = this.target; 
    String notifCheck2 = this.notifCheck2; 

    if(lastTime != null && notifCheck != null) { 
     if(!lastTime.equals("-1") && !notifCheck.equals("1")) 
      new Notifications(this).InviteUser(); 
    } else this.stopSelf(); 

    if(target != null && notifCheck2 != null) { 
     if(target.equals("") && !notifCheck2.equals("1")) 
      new Notifications(this).TargetlessNotification(); 
    } else this.stopSelf(); 

} 

}