Reputation: 7117
In my application I have a (background) Service
which runs in its own process. To communicate with other components I defined some AIDL interfaces:
interface MyService {
void addOnChangeListener(ServiceChangedListener listener);
void removeOnChangeListener(ServiceChangedListener listener);
}
interface ServiceChangedListener {
void onUserChanged(in User newUser);
}
Here is my service with the MyService
implementation.
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...
}
My Activity
connects to this Service
in onStart
and disconnects from it in onStop
where it also release the listener which is registered in 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(() -> { ... });
}
}
}
The add and remove methods for the listener simply operate on an ArrayList
as you would expect so there is no long ongoing work.
LeakCanary as well as the Android studio memory analysis tool tell me that this causes a memory leak. If I comment out the lines affecting the listener no memory leak is detected. Do you have any ideas why?
Upvotes: 2
Views: 862
Reputation: 7117
I finally found the answer! You have to make the inner class static and use a WeakReference
within it. Here is an official answer of a Google engineer and here a simplified one. Good luck anyone with the same problem!
Upvotes: 3