Closed rasmusohrstig closed 6 years ago
The leak actually happens even if you call Activity.finish() in Activity.onResume().
The workaround is to attach a listener: loginButton.addOnAttachStateChangeListener() and in View.OnAttachStateChangeListener.onViewAttachedToWindow() you can call Activity.finish().
The constructor of ConnectLoginButton calls CustomTabsClient.bindCustomTabsService() which binds a Service.
In order to avoid leaking that Service Context.unbindService() is called in ConnectLoginButton.onDetachedFromWindow().
This will prevent leaks in most situations, but there is a fairly common pattern where in Activity.onCreate() we inflate a layout that contains a ConnectLoginButton and then chose to do an early exit from the Activity by calling Activity.finish() in Activity.onCreate(). In this situation ConnectLoginButton.onDetachedFromWindow() is never called and we get a android.app.ServiceConnectionLeaked exception.
We can avoid this by never calling Activity.finish() before ConnectLoginButton.onAttachedToWindow() has been called, but that is just a workaround.
This blog post https://medium.com/square-corner-blog/android-leak-pattern-subscriptions-in-views-18f0860aa74c describes the problem and offers a better solution: only bind the Service in View.onAttachedToWindow(). This will always work since onDetachedFromWindow() is always called if onAttachedToWindow() has been called.