LeakCanary обнаружила утечку памяти для функции обратного вызова AppOpsManager OnOpChangedListener - PullRequest
0 голосов
/ 06 мая 2020

Я нахожу доступные утечки памяти в моем 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);
}

1 Ответ

0 голосов
/ 06 мая 2020

Я считаю (хотя вы этого не показали), что проблема в следующем:

  1. Вы регистрируете локальный объект в своем экземпляре (usageOpListener) для другого объекта, который вы получили косвенно через служба локатора системы (appOpsManager) во время вашего класса onCreate.
  2. Эта ссылка на YourActivity#OnOpChangedListener теперь является жесткой ссылкой внутри AppOpsManager.
  3. Затем вы ожидаете, что ссылка на go исчезнет, ​​когда ваша активность будет уничтожена, но ваша активность не всегда уничтожается Framework. Его можно остановить, но жесткая ссылка на него все еще присутствует в диспетчере AppOps.

Я бы переместил код запуска / остановки просмотра в onStart / onStop соответственно.

...