Activity 和 Service 之间的通信导致内存泄漏

Communication between Activity and Service causes memory leak

在我的应用程序中,我有一个(后台)Service,它在自己的进程中运行。为了与其他组件通信,我定义了一些 AIDL 接口:

interface MyService {
    void addOnChangeListener(ServiceChangedListener listener);
    void removeOnChangeListener(ServiceChangedListener listener);
}

interface ServiceChangedListener {
    void onUserChanged(in User newUser);
}

这是我的 MyService 实施服务。

public class UserService extends Service {
    private RemoteCallbackList<ServiceChangedListener> listeners;

    public class ServiceBinder extends MyService.Stub {
        public void addOnChangeListener(ServiceChangedListener listener) {
            listeners.register(listener);
        }

        public void removeOnChangeListener(ServiceChangedListener listener) {
            listeners.unregister(listener);
        }
    }

    // all the other implementation...
}

我的 ActivityonStart 中连接到此 Service 并在 onStop 中断开连接,同时释放在 onServiceConnected 中注册的侦听器.

public class MainAcitivity extends AppCompatActivity {
    private ServiceListener listener;
    private MyService service;

    protected void onStart() {
        super.onStart();

        Intent intent = new Intent(this, UserService.class);
        bindService(intent, this, Context.BIND_AUTO_CREATE);
    }

    protected void onStop() {
        super.onStop();

        try { service.removeOnChangeListener(listener); }
        catch (RemoteException e) { e.printStackTrace(); }

        unbindService(this);
    }

    public void onServiceConnected(ComponentName className, IBinder service) {
        service = MyService.Stub.asInterface(service);

        try {
            listener = new ServiceListener();
            service.addOnChangeListener(listener);
        } catch (RemoteException e) {
            e.printStackTrace();
        }
    }

    private class ServiceListener extends ServiceChangedListener.Stub {
        public void onUserChanged(User u) throws RemoteException {
            runOnUiThread(() -> { ... });
        }
    }
}

侦听器的添加和删除方法只是在 ArrayList 上运行,正如您所期望的那样,因此没有长期正在进行的工作。

LeakCanary 以及 Android studio 内存分析工具告诉我这会导致内存泄漏。如果我注释掉影响侦听器的行,则不会检测到内存泄漏。你知道为什么吗?

终于找到答案了!您必须使内部 class 静态化并在其中使用 WeakReference。这是一个 official answer of a Google engineer and here 的简化版。祝遇到同样问题的人好运!