Faltenreich / SkeletonLayout

Skeleton view pattern for Android
Apache License 2.0
505 stars 65 forks source link

Crash when parent's size is 0 #5

Closed ema987 closed 5 years ago

ema987 commented 5 years ago

Hello,

I haven't got enough time to investigate why this happens but sometimes the function private fun createBitmap(): Bitmap = Bitmap.createBitmap(parent.width, parent.height, Bitmap.Config.ALPHA_8) throws a java.lang.IllegalArgumentException: width and height must be > 0 because the size of the parent is equal to 0.

I've put on my fork a fast fix which is "check the size and if 0 use 1", but I don't think this is the way to correctly solve the issue, even if it works and the crash is avoided.

If needed you can check it here

Faltenreich commented 5 years ago

Thank you for your bug report and investigation! I will try to catch the problem before the IllegalArgumentException occurs. I assume lifecycle problems but I will take my time to find the root of this problem. Do you experience this bug when applying the skeleton to a View, to a RecyclerView or both? When this bug is fixed, I will release a new version including your androidx migration as well.

ema987 commented 5 years ago

Hello, thank you for your support. This is the scenario where the bug happens: RecyclerView which uses CustomViews to display information. The skeleton is applied to the CustomView (so not with recyclerView.applySkeleton() but directly on the CustomView xml). When you scroll the recyclerview the bug appears, probably due to view recycling.

I hope my description is enough, if you won't be able to reproduce it I'll try to take some time to make a simple project to reproduce it.

Faltenreich commented 5 years ago

Skeleton applied directly on View within a RecyclerView - that hint should point me in the right direction. I will try to reproduce it and investigate the problem. Thanks again and have nice day!

ema987 commented 5 years ago

@Faltenreich thank you very much for investigating this issue so fast. I've tried your 2.0.0 release but unfortunately the issue still appears (even if che changes you made look good to me)

Please see here a full stack trace of the crash, I hope it will help you to find out the issue.

java.lang.IllegalArgumentException: width and height must be > 0
        at android.graphics.Bitmap.createBitmap(Bitmap.java:877)
        at android.graphics.Bitmap.createBitmap(Bitmap.java:856)
        at android.graphics.Bitmap.createBitmap(Bitmap.java:823)
        at com.faltenreich.skeletonlayout.mask.SkeletonMask.createBitmap(SkeletonMask.kt:24)
        at com.faltenreich.skeletonlayout.mask.SkeletonMask$bitmap$2.invoke(SkeletonMask.kt:20)
        at com.faltenreich.skeletonlayout.mask.SkeletonMask$bitmap$2.invoke(SkeletonMask.kt:12)
        at kotlin.SynchronizedLazyImpl.getValue(LazyJVM.kt:74)
        at com.faltenreich.skeletonlayout.mask.SkeletonMask.getBitmap(SkeletonMask.kt)
        at com.faltenreich.skeletonlayout.mask.SkeletonMask.createCanvas(SkeletonMask.kt:26)
        at com.faltenreich.skeletonlayout.mask.SkeletonMask$canvas$2.invoke(SkeletonMask.kt:21)
        at com.faltenreich.skeletonlayout.mask.SkeletonMask$canvas$2.invoke(SkeletonMask.kt:12)
        at kotlin.SynchronizedLazyImpl.getValue(LazyJVM.kt:74)
        at com.faltenreich.skeletonlayout.mask.SkeletonMask.getCanvas(SkeletonMask.kt)
        at com.faltenreich.skeletonlayout.mask.SkeletonMask.draw(SkeletonMask.kt:39)
        at com.faltenreich.skeletonlayout.mask.SkeletonMask.maskView(SkeletonMask.kt:67)
        at com.faltenreich.skeletonlayout.mask.SkeletonMask.mask(SkeletonMask.kt:53)
        at com.faltenreich.skeletonlayout.mask.SkeletonMask.mask(SkeletonMask.kt:52)
        at com.faltenreich.skeletonlayout.mask.SkeletonMask.mask(SkeletonMask.kt:47)
        at com.faltenreich.skeletonlayout.SkeletonLayout.invalidateMask(SkeletonLayout.kt:159)
        at com.faltenreich.skeletonlayout.SkeletonLayout.showSkeleton(SkeletonLayout.kt:104)
        at com.faltenreich.skeletonlayout.SkeletonLayout.onLayout(SkeletonLayout.kt:120)
        at android.view.View.layout(View.java:17641)
        at android.view.ViewGroup.layout(ViewGroup.java:5575)
        at androidx.constraintlayout.widget.ConstraintLayout.onLayout(ConstraintLayout.java:1858)
        at android.view.View.layout(View.java:17641)
        at android.view.ViewGroup.layout(ViewGroup.java:5575)
        at android.widget.RelativeLayout.onLayout(RelativeLayout.java:1079)
        at android.view.View.layout(View.java:17641)
        at android.view.ViewGroup.layout(ViewGroup.java:5575)
        at androidx.constraintlayout.widget.ConstraintLayout.onLayout(ConstraintLayout.java:1858)
        at android.view.View.layout(View.java:17641)
        at android.view.ViewGroup.layout(ViewGroup.java:5575)
        at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1741)
        at android.widget.LinearLayout.layoutHorizontal(LinearLayout.java:1730)
        at android.widget.LinearLayout.onLayout(LinearLayout.java:1496)
        at android.view.View.layout(View.java:17641)
        at android.view.ViewGroup.layout(ViewGroup.java:5575)
        at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1741)
        at android.widget.LinearLayout.layoutHorizontal(LinearLayout.java:1730)
        at android.widget.LinearLayout.onLayout(LinearLayout.java:1496)
        at android.view.View.layout(View.java:17641)
        at android.view.ViewGroup.layout(ViewGroup.java:5575)
        at androidx.recyclerview.widget.RecyclerView$LayoutManager.layoutDecoratedWithMargins(RecyclerView.java:9322)
        at androidx.recyclerview.widget.LinearLayoutManager.layoutChunk(LinearLayoutManager.java:1615)
        at androidx.recyclerview.widget.LinearLayoutManager.fill(LinearLayoutManager.java:1517)
        at androidx.recyclerview.widget.LinearLayoutManager.onLayoutChildren(LinearLayoutManager.java:612)
        at androidx.recyclerview.widget.RecyclerView.dispatchLayoutStep2(RecyclerView.java:3924)
        at androidx.recyclerview.widget.RecyclerView.onMeasure(RecyclerView.java:3336)
        at android.view.View.measure(View.java:19861)
        at androidx.constraintlayout.widget.ConstraintLayout.internalMeasureChildren(ConstraintLayout.java:1212)
        at androidx.constraintlayout.widget.ConstraintLayout.onMeasure(ConstraintLayout.java:1552)
        at android.view.View.measure(View.java:19861)
        at androidx.constraintlayout.widget.ConstraintLayout.internalMeasureChildren(ConstraintLayout.java:1212)
2019-03-21 09:54:09.179 12552-12552/xx.xx.xxx E/AndroidRuntime:     at androidx.constraintlayout.widget.ConstraintLayout.onMeasure(ConstraintLayout.java:1552)
        at android.view.View.measure(View.java:19861)
        at androidx.recyclerview.widget.RecyclerView$LayoutManager.measureChildWithMargins(RecyclerView.java:9119)
        at androidx.recyclerview.widget.LinearLayoutManager.layoutChunk(LinearLayoutManager.java:1583)
        at androidx.recyclerview.widget.LinearLayoutManager.fill(LinearLayoutManager.java:1517)
        at androidx.recyclerview.widget.LinearLayoutManager.scrollBy(LinearLayoutManager.java:1331)
        at androidx.recyclerview.widget.LinearLayoutManager.scrollVerticallyBy(LinearLayoutManager.java:1075)
        at androidx.recyclerview.widget.RecyclerView.scrollStep(RecyclerView.java:1832)
        at androidx.recyclerview.widget.RecyclerView$ViewFlinger.run(RecyclerView.java:5067)
        at android.view.Choreographer$CallbackRecord.run(Choreographer.java:874)
        at android.view.Choreographer.doCallbacks(Choreographer.java:686)
        at android.view.Choreographer.doFrame(Choreographer.java:618)
        at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:860)
        at android.os.Handler.handleCallback(Handler.java:751)
        at android.os.Handler.dispatchMessage(Handler.java:95)
        at android.os.Looper.loop(Looper.java:154)
        at android.app.ActivityThread.main(ActivityThread.java:6236)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:891)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:781)
Faltenreich commented 5 years ago

Thanks for your stack trace. Could you please provide a stripped down version of your Fragment / Activity, Adapter, ViewHolder and potential custom Views that get masked by the skeleton? Either a code snippet or a working demo project would be fantastic for me to reproduce this problem. Thanks in advance and have a nice day!

KennyGoers commented 5 years ago

I ran into this as well, I'm using the last 1.x versions (not doing AndroidX yet :/) so if this comment isn't valid, let me know, but it's always possible that a parent might be 0 in width or height so need to defend against that. It's also possible that a view would be 0 at the time of the onCreate as inflation and final data can happen asynchronously.

I'll try to spend some time on this today or tomorrow, but I'll issue a pull request from the version prior to the latest

KennyGoers commented 5 years ago

Add this to your list_item.xml file under the LinearLayout and you'll get the crash:

<View
  android:layout_width="0dp"
  android:layout_height="0dp"
  />
ema987 commented 5 years ago

@Faltenreich I'm sorry I haven't yet got the time to put on a sample project. Probably now thanks to @KennyGoers 's hint it's not needed anymore and you can address the issue. I'll keep following the thread anyway to give support if needed.

Faltenreich commented 5 years ago

@KennyGoers The issue you describe has been fixed with version 2.0.0. Child views with invalid sizes are caught now. I was only able to reproduce this crash when masking a parent view with width and height of zero. This case will be caught now by commit https://github.com/Faltenreich/SkeletonLayout/commit/1ce62039fe2f25cae35c9da789790dcc7ea45e1f which will be part of the next version (since it is an edge case that should normally not occur).

@ema987 I think the case @KennyGoers described is not part of your problem, so a sample project would still be great in order to reproduce your problem.

Faltenreich commented 5 years ago

I will close this issue, since the crash can not be reproduced since version 2.0.0. Feel free to reopen this issue if there is concrete evidence for a reoccurrence of this bug including a sample project or code snippet.