fabioCollini / mv2m

Android MVVM lightweight library based on Android Data Binding
Apache License 2.0
181 stars 21 forks source link

Leak canary reports that the ViewModel.activity is leaking on rotation #5

Closed osiloke closed 8 years ago

osiloke commented 8 years ago

Hi, There seems to be a leaked activity instance in the ViewModel class, could this be related to the activity reference not nullified in the RetainedFragment.onDetach, i see there is no onDetache method. Form what i understand from the fragment lifecycle of a retainedfragment, onAttach and onDetach are called whenever the activity rotates.

osiloke commented 8 years ago

removing the activity field seems to mitigate this problem

fabioCollini commented 8 years ago

Hi, I tried the demo app using leak canary and no leaks are reported. The activity reference is set to null on onDestroy method of the activity/fragment that is't destroyed (not on an event of retained fragment). Can you provide more info about the error? Which device are you using? Which Android version?

osiloke commented 8 years ago

My device uses 5.1.1 API:22. My leak canary report suggests that the problem is here

subscribe(
                    b -> userCollegeLoading.set(b),
                    getToken(activityHolder.getActivity())
                            .flatMap(token -> userCollegeRepository.getUserCollege(token, model.getId()))
                            .compose(RepositoryUtils.<UserCollege>transformResult())
                            .asObservable(),
                    userCollege -> {
                        usercollege.set(userCollege);
                        isUserCollegeLoaded.set(true);
                    },
                    e -> {
                        Timber.e(e.toString());
                    }
            );

getToken(activityHolder.getActivity()) retrieves a user token from androids AccountManager. The full leak report is here

fabioCollini commented 8 years ago

Hi, what's the implementation of the getToken method? Do you retain a reference to the Activity in the callback? Do you need the Activity in this method? Maybe a Context can be used, so adding a getApplication invocation you can solve it.

osiloke commented 8 years ago

Thanks for the suggestion, the getToken method called accountManager.getAuthTokenByFeatures in an rx observable. I switched to using accountManager.blockingGetAuthToken.