首页 > 解决方案 > LeakCanary 为 AppOpsManager OnOpChangedListener 回调函数发现内存泄漏

问题描述

我在我的 Android 应用程序中发现了可用的内存泄漏,LeakCanary 总是说 AppOpsManager OnOpChangedListener 回调函数对 MainActivity 有泄漏。我在 google 和 SF 上搜索了很多,但没有找到任何解决方案。下面是我的代码,请帮助解决这个内存泄漏。

@Override
protected void onCreate(Bundle savedInstanceState) {    
    appOpsManager = (AppOpsManager) getApplicationContext().getSystemService(Context.APP_OPS_SERVICE);
    appOpsManager.startWatchingMode(AppOpsManager.OPSTR_GET_USAGE_STATS, getApplicationContext().getPackageName(), usageOpListener);
    }

private final AppOpsManager.OnOpChangedListener usageOpListener = new AppOpsManager.OnOpChangedListener() {
    @Override
    public void onOpChanged(String op, String packageName) {
        if (packageName == null || getApplicationContext().getPackageName().equals(packageName)) {
            if (AppOpsManager.OPSTR_GET_USAGE_STATS.equals(op)) {
                Intent myIntent = new Intent(getApplicationContext(), MainActivity.class);
                getApplicationContext().startActivity(myIntent);
            }
        }
    }
};

@Override
protected void onDestroy() {    
appOpsManager.stopWatchingMode(usageOpListener);
}

标签: androidmemory-leaksleakcanaryandroid-app-ops

解决方案


I believe (although you haven't shown it) that the problem is:

  1. You register a local object to your instance (usageOpListener) to another object that you obtained indirectly through the system locator service (appOpsManager) during your class' onCreate.
  2. This reference to YourActivity#OnOpChangedListener is now a hard reference inside the AppOpsManager.
  3. You then expect the reference to go away when your activity is destroyed, but your activity is not always destroyed by the Framework. It can be stopped, but the hard reference to it, is still present in the AppOps Manager.

I'd move the start/stop watching code to onStart/onStop respectively.


推荐阅读