leandroBorgesFerreira / LoadingButtonAndroid

A button to substitute the ProgressDialog
MIT License
1.94k stars 214 forks source link

Memory Leak when used in fragment(2.1.5 version) #144

Open LinasSkardzius opened 5 years ago

LinasSkardzius commented 5 years ago

Hi, CircularProgressButtonView will create memory leak in case when Activity has multiple fragments and one of Fragments implements CircularProgressButtonView. Memory leak will happen because LifecycleObserver is connected to Activity but not with a fragment that implemented it. So CircularProgressButton will have strong reference to Activity and the fragments won't release until activity is not destroyed.

leandroBorgesFerreira commented 5 years ago

makes sense, I'll take a look at this.

Frank1234 commented 4 years ago

I created this extension method that should fix it temporary, call it in onCreateView on all your progress buttons:


import android.content.Context
import android.view.ContextThemeWrapper
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleObserver
import androidx.lifecycle.LifecycleOwner
import br.com.simplepass.loadingbutton.customViews.ProgressButton

/**
 * Fixes leak, where ProgressButton is tied to the Activity's lifecycle. Issue: https://github.com/leandroBorgesFerreira/LoadingButtonAndroid/issues/144
 *
 * @param lifecycle the lifecycle to tie it to. In case of a Fragment, use the fragment view's lifecycle: [fragment.viewLifecycleOwner.lifecycle]
 */
fun ProgressButton.updateLifecycleObserver(lifecycle: Lifecycle?) {
    getContext().removeLifecycleObserver(this) // to fix the leak.
    lifecycle?.addObserver(this) // to fix leaking after the fragment's view is destroyed.
}

private fun Context.removeLifecycleObserver(observer: LifecycleObserver) {
    when (this) {
        is LifecycleOwner -> lifecycle.removeObserver(observer)
        is ContextThemeWrapper -> baseContext.removeLifecycleObserver(observer)
        is androidx.appcompat.view.ContextThemeWrapper -> baseContext.removeLifecycleObserver(observer)
    }
}
dominik59 commented 2 years ago

@Frank1234 solution works. Thank you for that, because we were about to get rid of this library because of RAM leakage. Your solution saved it :)

P.S. It's also applicable for 2.2.0 version.

Just for those whose don't know how to attach proper lifecycle in each of your fragments which contains circullar button you can add in onViewCreated:

nextBtn.updateLifecycleObserver(viewLifecycleOwner.lifecycle)

where nextBtn is your btn