There are at least two problem cases with ShimmerLayout animation logic.
- If the ShimmerLayout has parent view/container and you hide parent view, animation logic inside ShimmerLayout doesn't stop. For example, we have some xml
<androidx.cardview.widget.CardView
android:id="@+id/cardView"
android:layout_width="match_parent"
android:layout_height="48dp"
android:layout_margin="8dp"
android:visibility="gone">
<io.supercharge.shimmerlayout.ShimmerLayout
android:id="@+id/shimmer"
app:shimmer_auto_start="true"
style="@style/ShimmerLayout">
<View
android:layout_width="24dp"
android:layout_height="24dp"
android:layout_gravity="center_vertical|start"
android:layout_marginLeft="16dp"
android:background="@color/n7"/>
<View
android:layout_width="match_parent"
android:layout_height="16dp"
android:layout_gravity="center_vertical"
android:layout_marginLeft="64dp"
android:layout_marginRight="32dp"
android:background="@color/n7"/>
</io.supercharge.shimmerlayout.ShimmerLayout>
</androidx.cardview.widget.CardView>
then our ShimmerLayout will run recursivelly in startShimmerAnimation method, although we have not even shown it to the user.
- More than that it leads to memory leak when using Activity#recreate method:
a) ShimmerLayout#startShimmerAnimation subscribes to ViewTreeObserver#onPreDraw to detect own width;
b) ShimmerLayout don't stop animation logic when parent view becomes hidden or the ShimmerLayout is detached from the window.;
- com.example.app.MyFragment has leaked:
- static WindowManagerGlobal.sDefaultWindowManager
- ↳ WindowManagerGlobal.mRoots
- ↳ ArrayList.elementData
- ↳ array Object[].[0]
- ↳ ViewRootImpl.!(mAttachInfo)!
- ↳ View$AttachInfo.!(mTreeObserver)!
- ↳ ViewTreeObserver.!(mOnPreDrawListeners)!
- ↳ ViewTreeObserver$CopyOnWriteArray.!(mData)!
- ↳ ArrayList.!(elementData)!
- ↳ array Object[].!([1])!
- ↳ ShimmerLayout$1.!(this$0)! (anonymous implementation of android.view.ViewTreeObserver$OnPreDrawListener)
- ↳ ShimmerLayout.mContext
- ↳ MainActivity.navigationController
- ↳ DefaultBottomBarController.adapter
- ↳ CachePagerAdapter.mCurrentPrimaryItem
- ↳ MyFragment
There are at least two problem cases with ShimmerLayout animation logic.
<androidx.cardview.widget.CardView
android:id="@+id/cardView"
android:layout_width="match_parent"
android:layout_height="48dp"
android:layout_margin="8dp"
android:visibility="gone">
</androidx.cardview.widget.CardView>
then our ShimmerLayout will run recursivelly in startShimmerAnimation method, although we have not even shown it to the user.
a) ShimmerLayout#startShimmerAnimation subscribes to ViewTreeObserver#onPreDraw to detect own width;
b) ShimmerLayout don't stop animation logic when parent view becomes hidden or the ShimmerLayout is detached from the window.;