I have a TextureView which utilizes a background thread to paint content on a regular interval.
This all works well most of the time, but I've found that when scrolling this TextureView off the visible screen and back on sometimes causes isAvailable to be false and lockCanvas to return null. I don't know if this is about scrolling it into/out of view quickly is the issue, or something else.
I have a TextureViewListener attached and onSurfaceTextureAvailable does get called and isAvailable returns true from there. However, when the background thread tries to render just a few miliseconds after that, isAvailable is false and lockCanvas returns null, so it can't draw.
Sometimes scrolling the control back off the screen and back into view again fixes the issue and it will again repaint. I can find no explanation for this particular behavior anywhere, and no other question on Stack Overflow seems to address this.
This happens on at least Android 7 and 9 on multiple devices. Reproduction is not 100%, but after some number of tries, it always happens.
The background thread simply loops this code:
Canvas c = null;
try {
synchronized (this) {
c = lockCanvas(null);
render(c); // <-- does some drawing when c is not null
}
} finally {
if (c != null) {
unlockCanvasAndPost(c);
}
}
I solved this with a short delayed call to requestLayout(). For whatever reason, even though onSurfaceTextureAvailable is called and reports the texture as available, it isn't immediately afterwards. Requesting a new layout on a slight delay fixes the issue.