-
Notifications
You must be signed in to change notification settings - Fork 163
Description
This is using Androidplot 1.5.10.
Due to various degrees of nesting (e.g. XYPlot within a LinearLayout, within a fragment that replaces a FrameLayout of the fragment of a ViewPager2's page, ...), I've encountered a situation where the one of the dimensions of the XYPlot instance is 0, before being expended to its actual size later on.
(Apologies, I'm unable to re-create a small fully contained example.)
In this case, renderOnCanvas is called with a null Canvas, but when we're using a background thread, isIdle is never set to true in this case (as it would with non-zero dimensions).
As a result, the background thread is stuck waiting at renderSync.wait(), and the plot can never be rendered by resizing.
Details
In a situation where rendering is done in background-thread mode, this shows these logs:
plot.addOnLayoutChangeListener(
(view, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom) -> {
XYPlot plot = (XYPlot) view;
Log.d(TAG, String.format(
"Plot layout change: %s/%s/%s/%s -> %s/%s/%s/%s",
oldLeft, oldTop, oldRight, oldBottom,
left, top, right, bottom));
});D Plot layout change: 0/0/0/0 -> 0/0/1080/0
I Thread started with id 143665258
D Plot layout change: 0/0/1080/0 -> 0/53/1080/824
The problem here is that the background thread, and the first pass at rendering starts with a dimension of 0 height.
In this case, the Canvas in the pingPong instance is null, in Plot.startBackgroundrendering().
Indeed, the BufferedCanvas is resized using (0,0), which makes its bgBuffer null, and therefore makes getCanvas() return null.
As a result, renderOnCanvas returns straight away:
protected synchronized void renderOnCanvas(@Nullable Canvas canvas) {
if(canvas == null) {
return;
}The problem here, is that isIdle is never set to true (as it would with a non-null canvas).
As a result, redraw() never does anything, since isIdle is always false:
public void redraw() {
if (renderMode == RenderMode.USE_BACKGROUND_THREAD) {
// only enter synchronized block if the call is expected to block OR
// if the render thread is idle, so we know that we won't have to wait to
// obtain a lock.
if (renderThread != null && isIdle) {
synchronized (renderSync) {
renderSync.notify();
}
}
Because of that, renderSync.notify() can never be called, so the background thread is stuck at renderSync.wait(), so no further redrawing can take place.
Solution
Setting isIdle = true in Plot.renderOnCanvas seems to fix the problem:
protected synchronized void renderOnCanvas(@Nullable Canvas canvas) {
if(canvas == null) {
isIdle = true;
return;
}