-
Notifications
You must be signed in to change notification settings - Fork 727
[epoxy-paging] Crash in the PagedListEpoxyController when trying to invoke addTo
on a null model
#567
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
@yigit do you think it's a good idea to filter out nulls from the |
Putting this code in
|
that is weird, i sample to reproduce would be nice. I'm guessing the threading model is not working such that models are being modified in another thread. It is important that the notify thread of PagedList is the same as the buildModels thread of EpoxyController. The test uses LivePagedListBuilder so maybe something is not matching in the rx builder. |
Uh oh, I think I missed that. This is already not true for me because I have I'll try putting them on the same thread to see if that fixes the issue. |
After using Thank you so much for the debugging pointer, @yigit ! |
Looks like this crash is not trivial to troubleshoot. May be the framework could fail-fast in case notify scheduler is not on the same thread than the model building ? |
Thanks Yigit for the idea, glad that fixed it. I can update the documentation to make this requirement clear. It would be great to auto detect this issue, but from what I can tell there is no public way for Epoxy to see what notifyExecutor is set on the paged list. I'll reopen this as a reminder to make these changes |
I'm still seeing this crash. My screen is a vertical paged list that comes from the db. I prepend an item that has a horizontal epoxy controller. The information of this inner controller comes from the server. To show these new server items, im passing the list to the main epoxy controller and then I do I'm using the async epoxy handler everywhere except in the subscriber of the server call. This means that Any ideas? Thanks |
For the record, I download the latest epoxy source code and run the epoxy-pagingsample app, I could stably reproduce this crash with the following stack trace by scrolling it fast before it generates 3000 records.
|
For these who is interested in checking out the fix using Rxjava 2, please refer to this pull request. |
I noticed the sample issue too a little while back, looks like Thanks for sharing the rxjava sample @TonyTangAndroid ! |
Yeah, that's the reason why I made the attempt to use RxJava to check out whether it will crash or not after applying the hint from @rohandhruva . And it indeed turns out to be good. |
Wow~ the fix has already been merged into master. That's quick. Thank you for your quick response. |
Everyone is saying the fix worked. But I'm still seeing this crash even using the same thread. I haven't been able to pinpoint the problem yet. I'm using the Rx builder and using the epoxy async thread in both the builder and the two epoxy handlers (model build and diff). It's not frequent, but it happens. |
I've run into this same problem, and what we believed it to be is because of how I handle network state. I have two live data: one that has a state with my pagedlist of items, and another livedata that represents the network state. Because I did some research and found Perhaps that's what @kakai248 is still seeing? |
@AdamMc331 That's very likely as we only see crashes in controllers where we add additional models. However your proposed solution won't work for us as the additional models we add can't be delayed otherwise the screens get weird. We are delaying the submitList instead. But this is just a band-aid. I'm not sure where to start to solve the race condition. |
Yeah, I feel like our solution is a band aid too and isn't 💯 fool proof to preventing this race condition, but in practice and with some manual stress testing I haven't been able to break it. That's not to say it won't happen once it's out in the wild, though. :/ |
Works around airbnb/epoxy#567
https://drive.google.com/open?id=19j5cmY3jgYUWhPiVGvZEyec7LS1LDVTn This was the best I could do to reproduce the issue. It happens sometimes (keep in mind it's a race condition). Keep closing and opening the app until it happens. I notice that when it crashes I can see the first two gray items. I believe the Heads up: The code was adapted from another epoxy bug test project. It's quite confusing and doing weird things. The |
actually i added a log to Looks like it is happening because of this code:
It does not check the current thread before calling buildModels. @elihart is this intended?
|
@yigit thanks for pointing that out - it is intended for the first call to Beyond state restoration, doing the first model build synchronously prevents briefly flashing a white screen when the fragment is first displayed. I had forgotten about this in the discussion of Paged List synchronization and NPE issues though - this does seem like it would require manual synchronization to solve like in (#656) |
The problem is not the access to the model though. We build the model based on the PagedList provided by the async diff util. That PagedList updates its contents only on the notify thread (for thread safety). I'm thinking, maybe we can figure out a way to special case initial load and for other callbacks, we can consider checking the notify thread and if it is not the right looper, throwing a descriptive exception. This way, if the developer made a mistake of giving them different threads, they'll easily see the problem and fix it. Another, more expensive, option is to copy the PagedList contents into the builder thread automatically as notifications arrive, with some message passing. It will be yet another copy of the list (and we already have 1 because of the models) but that would also make building use its own data structure that it can safely access. wdyt? I like the first option better if we can figure out a way to special case initial call and ensure everything else will be on the right thread. |
Thanks for explaining, I see the issues now. I like your ideas for the first option. I updated #656 with a potential solution. Basically it skips using the model cache when the looper isn't the expected one for model building. Another edge case I noticed is that |
This will hopefully be fixed with #656 |
While trying to implement paged list + paged controller, I run into a crash that's not reliably reproducible. The crash seems to happen around 1 in 7 times, completely anecdotally.
I'm attaching the stack trace: note how my custom controller (that extends
PagedListEpoxyController
) is not in the stack trace because the crash happens inPagedListEpoxyController
internals.I will try to get a small sample app with a reliable reproducible test case. In the meantime, some information that could be useful:
MyImplementationPagedListController
, I have these two params:modelBuildingHandler = EpoxyAsyncUtil.getAsyncBackgroundHandler()
diffingHandler = EpoxyAsyncUtil.getAsyncBackgroundHandler()
RxPagedListBuilder
withsetFetchScheduler(Schedulers.io())
I noticed that
PagedListModelCache
holdsnull
models, I am guessing one of those is likely mistakenly being passed through ingetModels()
.The text was updated successfully, but these errors were encountered: