Summary
I have made a custom BarChartRenderer to display icons below each column(code below). it is implemented inside recycle viewHolder in setData method triggered from addapter's onBind().
Now when i scroll the recycler fast i get an exception thrown from the library. note that when i disable the custom renderer there is not error.
java.lang.NullPointerException: Attempt to read from null array
at com.github.mikephil.charting.renderer.BarChartRenderer.drawDataSet(BarChartRenderer.java:136)
at com.github.mikephil.charting.renderer.BarChartRenderer.drawData(BarChartRenderer.java:80)
at com.github.mikephil.charting.charts.BarLineChartBase.onDraw(BarLineChartBase.java:231)
at android.view.View.draw(View.java:16178)
at android.view.View.updateDisplayListIfDirty(View.java:15174)
at android.view.View.draw(View.java:15948)
at android.view.ViewGroup.drawChild(ViewGroup.java:3609)
at android.view.ViewGroup.dispatchDraw(ViewGroup.java:3399)
at android.view.View.updateDisplayListIfDirty(View.java:15169)
at android.view.View.draw(View.java:15948)
at android.view.ViewGroup.drawChild(ViewGroup.java:3609)
at android.view.ViewGroup.dispatchDraw(ViewGroup.java:3399)
at android.view.View.draw(View.java:16181)
at android.view.View.updateDisplayListIfDirty(View.java:15174)
at android.view.View.draw(View.java:15948)
at android.view.ViewGroup.drawChild(ViewGroup.java:3609)
at android.support.v7.widget.RecyclerView.drawChild(RecyclerView.java:4703)
at android.view.ViewGroup.dispatchDraw(ViewGroup.java:3399)
at android.view.View.draw(View.java:16181)
at android.support.v7.widget.RecyclerView.draw(RecyclerView.java:4107)
at android.view.View.updateDisplayListIfDirty(View.java:15174)
at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:3593)
at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:3573)
at android.view.View.updateDisplayListIfDirty(View.java:15134)
at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:3593)
at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:3573)
at android.view.View.updateDisplayListIfDirty(View.java:15134)
at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:3593)
at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:3573)
at android.view.View.updateDisplayListIfDirty(View.java:15134)
at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:3593)
at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:3573)
at android.view.View.updateDisplayListIfDirty(View.java:15134)
at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:3593)
at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:3573)
at android.view.View.updateDisplayListIfDirty(View.java:15134)
at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:3593)
at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:3573)
at android.view.View.updateDisplayListIfDirty(View.java:15134)
at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:3593)
at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:3573)
at android.view.View.updateDisplayListIfDirty(View.java:15134)
at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:3593)
at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:3573)
at android.view.View.updateDisplayListIfDirty(View.java:15134)
at android.view.ThreadedRenderer.updateViewTreeDisplayList(ThreadedRenderer.java:281)
at android.view.ThreadedRenderer.updateRootDisplayList(ThreadedRenderer.java:287)
at android.view.ThreadedRenderer.draw(ThreadedRenderer.java:322)
at android.view.ViewRootImpl.draw(ViewRootImpl.java:2615)
at android.view.ViewRootImpl.performDraw(ViewRootImpl.java:2434)
at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:2067)
at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1107)
at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:6013)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:858)
at android.view.Choreographer.doCallbacks(Choreographer.java:670)
at android.view.Choreographer.doFrame(Choreographer.java:606)
at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:844)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.ja
my custom render
`class BarChartCustomRenderer(chart: BarDataProvider, animator: ChartAnimator, viewPortHandler: ViewPortHandler, private val imageList: ArrayList
override fun drawValues(canvas: Canvas) {
val dataSets = mChart.barData.dataSets
val valueOffsetPlus = Utils.convertDpToPixel(OFF_SET_VALUE)
var negOffset: Float
for (i in 0 until mChart.barData.dataSetCount) {
val dataSet = dataSets[i]
applyValueTextStyle(dataSet)
val valueTextHeight = Utils.calcTextHeight(mValuePaint, "8").toFloat()
negOffset = valueTextHeight + valueOffsetPlus
val buffer = mBarBuffers[i]
var left: Float
var right: Float
var top: Float
var bottom: Float
var columnIndex = 0
while (columnIndex < buffer.buffer.size * mAnimator.phaseX) {
left = buffer.buffer[columnIndex]
top = buffer.buffer[columnIndex + 1]
right = buffer.buffer[columnIndex + 2]
bottom = buffer.buffer[columnIndex + 3]
val xCenter = (left + right) / 2
if (!mViewPortHandler.isInBoundsRight(xCenter))
break
if (!mViewPortHandler.isInBoundsY(top) || !mViewPortHandler.isInBoundsLeft(xCenter)) {
columnIndex += 4
continue
}
val entry = dataSet.getEntryForIndex(columnIndex / 4)
val yValue = entry.y
mValuePaint.textAlign = Paint.Align.CENTER
if (yValue > 0) {
drawValue(canvas, dataSet.valueFormatter, yValue, entry, i, xCenter, top - 4, dataSet.getValueTextColor(columnIndex / 4))
}
val bitmap = imageList[columnIndex / 4]
val scaledBitmap = getScaledBitmap(bitmap)
canvas.drawBitmap(scaledBitmap, xCenter - scaledBitmap.width / 2, bottom + 0.5F * negOffset - scaledBitmap.width / 2F, null)
scaledBitmap.recycle()
columnIndex += 4
}
}
}
private fun getScaledBitmap(bitmap: Bitmap): Bitmap {
val width = context.resources.getDimension(R.dimen.dimen_18).toInt()
val height = context.resources.getDimension(R.dimen.dimen_18).toInt()
return Bitmap.createScaledBitmap(bitmap, width, height, true)
}
}`
Expected Behavior
The viewHolder is properly binded and no error on draw happens
Possible Solution
not a clue :/
Device (please complete the following information):
for anybody else who encounters this problem. override onDraw()and initBuffers() there before super.onDraw()
@czerwix Thanks for this helped me out.
initBuffers() needs to be called in the drawData() method now though, there is no onDraw() to override.
Most helpful comment
@czerwix Thanks for this helped me out.
initBuffers()needs to be called in thedrawData()method now though, there is noonDraw()to override.