LeakCanary сообщает AppOpsManager
утечка памяти, когда я думаю, что это не должно произойти (на основании OnOpChangedListener
перезапуска). Я что-то не так делаю?
Запрос разрешений:
AppOpsManager.OnOpChangedListener onOpChangedListener = null;
AppOpsManager appOpsManager = null;
public void requestUsagePermissionAndWait(){
appOpsManager = (AppOpsManager) getContext().getSystemService(Context.APP_OPS_SERVICE);
onOpChangedListener = new AppOpsManager.OnOpChangedListener(){
@Override public void onOpChanged(String op, String packageName) {
if(appOpsManager != null){
appOpsManager.stopWatchingMode(this);
if(onOpChangedListener != null){
appOpsManager.stopWatchingMode(onOpChangedListener);
onOpChangedListener = null;
}
appOpsManager = null;
}
((Activity) getContext()).runOnUiThread(new Runnable() {
@Override
public void run() {
onPermissionGranted();
}
});
}
};
appOpsManager.startWatchingMode(AppOpsManager.OPSTR_GET_USAGE_STATS, getContext().getPackageName(), onOpChangedListener);
}
Журнал LeakCanary:
D/LeakCanary: ┬
D/LeakCanary: ├─ android.app.AppOpsManager$1
D/LeakCanary: │ Leaking: UNKNOWN
D/LeakCanary: │ Anonymous subclass of com.android.internal.app.IAppOpsCallback$Stub
D/LeakCanary: │ GC Root: Global variable in native code
D/LeakCanary: │ ↓ AppOpsManager$1.val$callback
D/LeakCanary: │ ~~~~~~~~~~~~
D/LeakCanary: ├─ com.abc.zxy.views.MyCustomView$9
D/LeakCanary: │ Leaking: UNKNOWN
D/LeakCanary: │ Anonymous class implementing android.app.AppOpsManager$OnOpChangedListener
D/LeakCanary: │ ↓ MyCustomView$9.this$0
D/LeakCanary: │ ~~~~~~
D/LeakCanary: ├─ com.abc.zxy.views.MyCustomView
D/LeakCanary: │ Leaking: YES (View.mContext references a destroyed activity)
D/LeakCanary: │ mContext instance of com.abc.zxy.activities.ActivityMain with mDestroyed = true
D/LeakCanary: │ View#mParent is set
D/LeakCanary: │ View#mAttachInfo is null (view detached)
D/LeakCanary: │ View.mWindowAttachCount = 1
D/LeakCanary: │ ↓ MyCustomView.mParent
D/LeakCanary: ├─ android.widget.LinearLayout
D/LeakCanary: │ Leaking: YES (MyCustomView↑ is leaking and View.mContext references a destroyed activity)
D/LeakCanary: │ mContext instance of com.abc.zxy.activities.ActivityMain with mDestroyed = true
D/LeakCanary: │ View#mParent is set
D/LeakCanary: │ View#mAttachInfo is null (view detached)
D/LeakCanary: │ View.mWindowAttachCount = 1
D/LeakCanary: │ ↓ LinearLayout.mParent
D/LeakCanary: ├─ android.widget.LinearLayout
D/LeakCanary: │ Leaking: YES (LinearLayout↑ is leaking and View.mContext references a destroyed activity)
D/LeakCanary: │ mContext instance of com.abc.zxy.activities.ActivityMain with mDestroyed = true
D/LeakCanary: │ View#mParent is set
D/LeakCanary: │ View#mAttachInfo is null (view detached)
D/LeakCanary: │ View.mWindowAttachCount = 1
D/LeakCanary: │ ↓ LinearLayout.mParent
D/LeakCanary: ├─ android.widget.ScrollView
D/LeakCanary: │ Leaking: YES (LinearLayout↑ is leaking and View.mContext references a destroyed activity)
D/LeakCanary: │ mContext instance of com.abc.zxy.activities.ActivityMain with mDestroyed = true
D/LeakCanary: │ View#mParent is set
D/LeakCanary: │ View#mAttachInfo is null (view detached)
D/LeakCanary: │ View.mWindowAttachCount = 1
D/LeakCanary: │ ↓ ScrollView.mParent
D/LeakCanary: ╰→ android.support.constraint.ConstraintLayout
D/LeakCanary: Leaking: YES (ScrollView↑ is leaking and View.mContext references a destroyed activity and ObjectWatcher was watching this)
D/LeakCanary: mContext instance of com.abc.zxy.activities.ActivityMain with mDestroyed = true
D/LeakCanary: View#mParent is null
D/LeakCanary: View#mAttachInfo is null (view detached)
D/LeakCanary: View.mWindowAttachCount = 1
D/LeakCanary: key = 1dcc6d06-d2f2-4e0a-a6d8-ea6ae6688596
D/LeakCanary: watchDurationMillis = 5488
D/LeakCanary: retainedDurationMillis = 487