ここに記載されているように、開発中にStrictModeをアクティブにしてアプリを実行しています 下位プラットフォームバージョンの場合はStrictMode 。
Android.os.StrictMode$InstanceCountViolation
にinstances
およびlimit
の値を指定します。
インスタンス= 3; limit = 2
今私は疑問に思っています:
何か案は?
ActivityThread.performLaunchActivity
Activity
インスタンスを作成した直後。ActivityThread.performDestroyActivity
したがって、アクティビティが破棄されるたびにlimit
は小さくなりますが、インスタンスがリークした場合、実際のインスタンスカウントは制限より大きくなり、リークしたかどうかを検出するために、GCマジック(decrementExpectedActivityCount
):
System.gc();
System.runFinalization(); // added in https://github.com/Android/platform_frameworks_base/commit/6f3a38f3afd79ed6dddcef5c83cb442d6749e2ff
System.gc();
この後、GCがアプリのメモリからアクティビティを削除しなかった場合、リークと見なされます。
上記に基づいて、防止する唯一の方法は、onDestroy
の後に問題のあるアクティビティへの参照がないことを確認することです。問題は、いくつかのWeakReference
sがいくつかのネイティブオブジェクトを介してまだアクセス可能であり、ライフサイクルが異なるように見えることです。この結論に至った経緯は次のとおりです。
MyActivity
からバックアウトし、ログメッセージを表示した後select * from instanceof full.package.name.of.MyActivity
最初にカウントを増やす の場合、特定のクラスのリークを報告する前により多くのレッグルームがあります。
// Application.onCreate or nearby where you set up StrictMode detectActivityLeaks
Method incrementExpectedActivityCount = StrictMode.class.getMethod("incrementExpectedActivityCount", Class.class)
incrementExpectedActivityCount.invoke(null, MyActivity.class);
incrementExpectedActivityCount.invoke(null, MyActivity2.class);
一部のデバイスのStrictModeチェックにバグがあるようです。
アクティビティが開始され、すぐに終了して再起動されると、StrictMode.InstanceCountViolationを取得できます。
ただし、これは単にガベージコレクターがアクティビティの最初のインスタンスをまだ完了していないためです。つまり、一時的に2つ(またはそれ以上)のインスタンスがメモリにあります。
StartActivity()またはstartActivityForResult()の前にSystem.gc()を呼び出すと、StrictMode.InstanceCountViolationが停止します。
これは、StrictModeチェックのバグ(または機能かどうか)を示しているようです。
StrictMode InstanceCountViolation の処理に関するGoogleグループの説明を次に示します。すべての異なるAndroidバージョンには異なるポリシーがあるため、単に無効にするようです。また、Android docs say about Strict Mode
ただし、StrictModeで検出されたすべてを修正する必要はありません。特に、通常のアクティビティのライフサイクルでは、多くの場合、ディスクアクセスの多くのケースが必要です。 StrictModeを使用して、誤って行ったことを見つけます。ただし、UIスレッドでのネットワーク要求はほとんどの場合問題です。
それが@sriが彼のコードで見せようとしていることだと思います。
public class MyApplication extends Application {
@Override
public void onCreate (){
super.onCreate();
// when you create a new application you can set the Thread and VM Policy
StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()
.detectCustomSlowCalls() // API level 11, to use with StrictMode.noteSlowCode
.detectDiskReads()
.detectDiskWrites()
.detectNetwork()
.penaltyLog()
.penaltyFlashScreen() // API level 11
.build());
//If you use StrictMode you might as well define a VM policy too
StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder()
.detectLeakedSqlLiteObjects()
.detectLeakedClosableObjects() // API level 11
.setClassInstanceLimit(Class.forName(“com.apress.proandroid.SomeClass”), 100)
.penaltyLog()
.build());
}
}
私の理解では、この違反はメモリリークの検出に使用されます。その時点で、クラスのインスタンスを2つだけロードする必要がありますが、VM found 3。
この違反はコードでも見ましたが、余分なインスタンスはすべて弱いポインターによって参照されていました。そこで、このルールを無効にすることにしました。