Closed xtknight closed 6 years ago
Thanks @xtknight for the excellent bug report and possible solution.
That said, I have not been able to recreate the error. I've added blocks to dev tests that I believe reflect the scenario you've described. I've run this on the emulator with several Android API levels. None crash.
Can you provide an example block and toolbox where you see this problem?
Looking through the code, I see that line is already wrapped in a null check for mImageField. That generally should protect from the NullPointerException in you stack trace.
It looks like there is a possible race condition between setField(..)
and updateViewSize()
(possible from the AsyncTask post execute). I've added code to protect against that, but I don't have a fail case to test whether it solves the problem.
Thank you for investigating. This does seem to be fixed on the latest version! If I use the new code in updateViewSize() to check null for mImageField, it seems to fix the problem. I thought I had checked the diff between the BasicFieldImageView I had and the latest git version but I guess I just missed it. But I guess it doesn't hurt to add the test for regression testing purposes anyway. Apparently the fix was already issued when this person had the problem: https://groups.google.com/d/msg/blockly/lC91XADUiI4/Y0cLRAYQBQAJ
Although this is a different issue, the image loading does seem awful slow (each get updated one-by-one) when using multiple blocks.
Although this is a different issue, the image loading does seem awful slow (each get updated one-by-one) when using multiple blocks.
Yes. I hadn't realized how bad that code was until investigating this issue. It needs a local cache, a way to update multiple fields looking at the same image, and ideally a pool of threads specific for network requests (as opposed to local disk I/O, which should be very fast). I'll put up some help-wanted issues for all of these.
I suppose loading images from the network in this case may not be the most common use case but very attentive to detail. Thanks!
Going to close this for now since it's not a crash in HEAD and regression tests have been added.
When using blocks containing an image, if we switch Blockly categories too quickly, there is the possibility of a crash. This is in production code and we have copied the Blockly module source code into our project and are compiling directly due to the need for customizations.
(Placing around 10 BasicFieldImageViews referencing an image from a network resource in a few categories and switching between them fast should be enough to reproduce the issue. Reproducible in emulator.) I suppose even if it's not a network resource, the possibility for a crash could still exist depending on how long it takes to load the resource from the desired media. I suppose it's fundamentally unsafe to run an asynchronous task and at an undefined time destroy what it relies on causing a null dereference, despite the fact that the case may be rare.
It seems to be because when the category changes, the layout of the ImageView gets destroyed but yet updateViewSize() gets called. It seems sufficient to busy-wait for the AsyncTask of downloading the image to be complete. I don't know if this is the "proper" solution but it seems to work for us so I wanted to share. Nor have I had the opportunity to try this on the latest git revision but wanted to provide this solution as reference for others.
BasicFieldImageView.java (startLoadingImage function):
TL;DR: workaround, not patch