私は、アプリケーションの重大なメモリリークの問題を特定し、アクティビティがすぐに作成/破棄されたときに(またはおそらくはすぐに再開/一時停止するときに)私はテストに基づいて考えているもの)。メモリリーク管理サービスの接続onアクティビティonResume/onPause
私は、これを引き起こしていることとそれを正しく修正する方法を理解するのに役立つと思います。 これは、別のアプリから別のアプリに切り替わり、画面の向きが違う(接続オブジェクトを保持している自分のアクティビティがフォアグラウンドにない)場合に発生します。
GCルートの 'LoadedApk $ ServiceDispatcher $ DeathMonitor'オブジェクトによって参照されているように見えるため、ガベージコレクションの対象にならないようなアクティビティがあります。
私はonResume()でbindを呼び出し、onPause()でunBindを呼び出します。 いくつかの実験をした後、問題の根本原因を何とかバインド/アンバインドする方法を信じています。例えば、私がバインドを解除すると、メモリリークは止まりますが、ConnectionLeakedの例外がいくつか発生します(原因はわかります)。 接続オブジェクトが通知を受け取る前にunbindを呼び出していると、何らかの理由でこの問題が発生しています(ただし、logcatでエラーが表示されず、サービスがbind/unbind呼び出しを適切に受け取ります)。 (私は前後に私のアプリと他のアプリとの間に数回を切り替えた後)私はEclipseのメモリアナライザを使用する場合
私はGCルートへの次のパスで活動インスタンスの束を参照してください。
MyActivityを
< --mContext android.app.LoadedApk $ ServiceDispatcher @
< 0x41059d6 ----この$ 0 android.app.LoadedApk $ ServiceDispatcher $ DeathMonitor @ネイティブスタック0x4105b548
私のソースコードは、基本的には、次のとおりです。
public class MyActivity extends Activity {
private final String TAG = "MyActivity";
public IREventService mREventService;
private ServiceConnection mConnection = new ServiceConnection() {
// Called when the connection with the service is established
public void onServiceConnected(ComponentName className, IBinder service) {
mREventService = IREventService.Stub.asInterface(service);
Log.e(TAG, "connected to service:"+MyActivity.this.toString()+ "connection: "+this.toString());
}
// Called when the connection with the service disconnects unexpectedly
public void onServiceDisconnected(ComponentName className) {
Log.e(TAG, "Service has unexpectedly disconnected:"+this.toString());
mREventService = null;
}
};
@Override
protected void onResume() {
super.onResume();
Intent intent = new Intent(this, EventService.class);
intent.setAction(this.toString());
Log.w(TAG, "bindService:"+this.toString());
bindService(intent,
mConnection, Context.BIND_AUTO_CREATE);
}
@Override
protected void onPause() {
super.onPause();
Log.w(TAG, "unbinding from service:"+this.toString());
unbindService(mConnection);
}
}
logcatsログは次のようになります。助けを
<I switched to another app>
06-17 17:27:08.965: WARN/MyActivity(5987): MyActivity onStop()
<this is where i switch back to my app>
06-17 17:27:09.415: INFO/ActivityManager(154): Config changed: { scale=1.0 imsi=310/4 loc=en_US touch=3 keys=1/1/2 nav=1/2 orien=L layout=0x10000014 uiMode=0x11 seq=169}
06-17 17:29:44.855: WARN/MyActivity(5987): MyActivity onDestroy()
06-17 17:29:44.855: INFO/TabletStatusBar(205): DISABLE_BACK: no
06-17 17:29:45.015: WARN/MyActivity(5987): MyActivity onCreate()
06-17 17:29:45.015: WARN/MyActivity(5987): MyActivity onResume()
06-17 17:29:45.015: WARN/MyActivity(5987): bindService:[email protected]
06-17 17:29:45.015: WARN/EventService(6009): onBind() [email protected]
06-17 17:29:45.025: WARN/MyActivity(5987): MyActivity onPause()
06-17 17:29:45.025: WARN/MyActivity(5987): unbinding from service:[email protected]
06-17 17:29:45.025: WARN/EventService(6009): onUnBind() [email protected]
06-17 17:29:45.025: ERROR/MyActivity(5987): connected to service:[email protected]: [email protected]
06-17 17:29:45.065: DEBUG/dalvikvm(5987): GC_FOR_ALLOC freed 32K, 3% free 31936K/32839K, paused 34ms
06-17 17:29:45.125: DEBUG/dalvikvm(5987): GC_FOR_ALLOC freed 65K, 4% free 32895K/33927K, paused 36ms
06-17 17:29:45.205: DEBUG/dalvikvm(5987): GC_FOR_ALLOC freed 803K, 5% free 33550K/35079K, paused 30ms
06-17 17:29:45.245: DEBUG/dalvikvm(5987): GC_FOR_ALLOC freed 65K, 4% free 34109K/35335K, paused 27ms
06-17 17:29:45.255: INFO/dalvikvm-heap(5987): Grow heap (frag case) to 36.976MB for 3722256-byte allocation
06-17 17:29:45.285: DEBUG/dalvikvm(5987): GC_FOR_ALLOC freed <1K, 4% free 37744K/38983K, paused 25ms
06-17 17:29:45.335: DEBUG/dalvikvm(5987): GC_CONCURRENT freed <1K, 4% free 37744K/38983K, paused 2ms+3ms
06-17 17:29:45.645: INFO/WindowManager(154): Setting rotation to 3, animFlags=1
06-17 17:29:45.665: INFO/ActivityManager(154): Config changed: { scale=1.0 imsi=310/4 loc=en_US touch=3 keys=1/1/2 nav=1/2 orien=P layout=0x10000014 uiMode=0x11 seq=170}
06-17 17:29:45.685: DEBUG/FlurryAgent(5770): Ending session
06-17 17:29:45.755: WARN/MyActivity(5987): MyActivity onStop()
06-17 17:29:45.755: WARN/MyActivity(5987): MyActivity onDestroy()
06-17 17:29:45.755: WARN/IInputConnectionWrapper(5770): showStatusIcon on inactive InputConnection
06-17 17:29:45.865: WARN/MyActivity(5987): MyActivity onCreate()
06-17 17:29:45.865: WARN/MyActivity(5987): MyActivity onResume()
06-17 17:29:45.865: WARN/MyActivity(5987): bindService:[email protected]
06-17 17:29:45.875: WARN/EventService(6009): onBind() [email protected]
06-17 17:29:45.875: WARN/MyActivity(5987): MyActivity onPause()
06-17 17:29:45.875: WARN/MyActivity(5987): unbinding from service:[email protected]
06-17 17:29:45.875: WARN/EventService(6009): onUnBind() [email protected]
06-17 17:29:45.875: ERROR/MyActivity(5987): connected to service:[email protected]: [email protected]
06-17 17:29:45.925: DEBUG/dalvikvm(5987): GC_FOR_ALLOC freed 6130K, 18% free 32743K/39815K, paused 24ms
06-17 17:29:46.005: DEBUG/dalvikvm(5987): GC_FOR_ALLOC freed 883K, 16% free 33737K/39815K, paused 23ms
06-17 17:29:46.035: DEBUG/dalvikvm(5987): GC_FOR_ALLOC freed 1K, 15% free 33970K/39815K, paused 23ms
おかげで(のEventServiceサービスである、と私は([OnBind]の中にログインしています)とonUnBind()) 。
この回答に少し追加しますか? http://developer.android.com/guide/components/bound-services.htmlでは、サンプルコードはonServiceConnected内でtrueに設定された変数mBoundを使用します。したがって、mBoundがtrueの場合にのみunbindを呼び出します。しかし、私は、サンプルコードのアプローチに従えば、onServiceConnectedは、アクティビティが停止または破棄された後でも、最終的に呼び出される可能性が非常に低いと考えていました。おそらくonServiceConnected内には、onStop(またはonDestroy)が呼び出されたかどうかをチェックし、そこからunbindを呼び出すブール値があるかもしれません。 –