X Tutup
Skip to content

Commit b5da8dc

Browse files
Crash fix - Create small clip paths (PhilJay#1895)
With large data sets, the Path object created was sufficiently large as to cause an OutOfMemory error. This is resolved by only pathing a limited number of points on the chart at a time, then clearing the path and resuming. Stress testing with 1500 entries.
1 parent 8775860 commit b5da8dc

File tree

3 files changed

+64
-30
lines changed

3 files changed

+64
-30
lines changed

MPChartExample/res/layout/activity_linechart.xml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
android:layout_margin="8dp"
1919
android:layout_toLeftOf="@+id/tvYMax"
2020
android:layout_marginRight="5dp"
21-
android:max="200"
21+
android:max="150"
2222
android:paddingBottom="12dp" />
2323

2424
<SeekBar
@@ -30,7 +30,7 @@
3030
android:layout_marginBottom="35dp"
3131
android:layout_toLeftOf="@+id/tvXMax"
3232
android:layout_marginRight="5dp"
33-
android:max="500"
33+
android:max="1500"
3434
android:paddingBottom="12dp" />
3535

3636
<TextView

MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ protected void onCreate(Bundle savedInstanceState) {
111111

112112
Typeface tf = Typeface.createFromAsset(getAssets(), "OpenSans-Regular.ttf");
113113

114-
LimitLine ll1 = new LimitLine(130f, "Upper Limit");
114+
LimitLine ll1 = new LimitLine(150f, "Upper Limit");
115115
ll1.setLineWidth(4f);
116116
ll1.enableDashedLine(10f, 10f, 0f);
117117
ll1.setLabelPosition(LimitLabelPosition.RIGHT_TOP);
@@ -129,7 +129,7 @@ protected void onCreate(Bundle savedInstanceState) {
129129
leftAxis.removeAllLimitLines(); // reset all limit lines to avoid overlapping lines
130130
leftAxis.addLimitLine(ll1);
131131
leftAxis.addLimitLine(ll2);
132-
leftAxis.setAxisMaxValue(220f);
132+
leftAxis.setAxisMaxValue(200f);
133133
leftAxis.setAxisMinValue(-50f);
134134
//leftAxis.setYOffset(20f);
135135
leftAxis.enableGridDashedLine(10f, 10f, 0f);

MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineChartRenderer.java

Lines changed: 60 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -449,6 +449,8 @@ protected void drawLinear(Canvas c, ILineDataSet dataSet) {
449449
}
450450
}
451451

452+
protected Path mGenerateFilledPathBuffer = new Path();
453+
452454
/**
453455
* Draws a filled linear path on the canvas.
454456
*
@@ -459,60 +461,92 @@ protected void drawLinear(Canvas c, ILineDataSet dataSet) {
459461
*/
460462
protected void drawLinearFill(Canvas c, ILineDataSet dataSet, Transformer trans, XBounds bounds) {
461463

462-
Path filled = generateFilledPath(dataSet, bounds);
464+
final Path filled = mGenerateFilledPathBuffer;
463465

464-
trans.pathValueToPixel(filled);
466+
final int startingIndex = bounds.min;
467+
final int endingIndex = bounds.range + bounds.min;
468+
final int indexInterval = 128;
465469

466-
final Drawable drawable = dataSet.getFillDrawable();
467-
if (drawable != null) {
470+
int currentStartIndex = 0;
471+
int currentEndIndex = indexInterval;
472+
int iterations = 0;
468473

469-
drawFilledPath(c, filled, drawable);
470-
} else {
474+
// Doing this iteratively in order to avoid OutOfMemory errors that can happen on large bounds sets.
475+
do{
476+
currentStartIndex = startingIndex + (iterations * indexInterval);
477+
currentEndIndex = currentStartIndex + indexInterval;
478+
currentEndIndex = currentEndIndex > endingIndex ? endingIndex : currentEndIndex;
479+
480+
if(currentStartIndex <= currentEndIndex) {
481+
generateFilledPath(dataSet, currentStartIndex, currentEndIndex, filled);
482+
483+
484+
485+
trans.pathValueToPixel(filled);
486+
487+
final Drawable drawable = dataSet.getFillDrawable();
488+
if (drawable != null) {
489+
490+
drawFilledPath(c, filled, drawable);
491+
} else {
492+
493+
drawFilledPath(c, filled, dataSet.getFillColor(), dataSet.getFillAlpha());
494+
}
495+
}
496+
497+
iterations++;
498+
499+
}while(currentStartIndex <= currentEndIndex);
471500

472-
drawFilledPath(c, filled, dataSet.getFillColor(), dataSet.getFillAlpha());
473-
}
474501
}
475502

476-
protected Path mGenerateFilledPathBuffer = new Path();
477503
/**
478-
* Generates the path that is used for filled drawing.
504+
* Generates a path that is used for filled drawing.
505+
*
506+
* @param dataSet The dataset from which to read the entries.
507+
* @param startIndex The index from which to start reading the dataset
508+
* @param endIndex The index from which to stop reading the dataset
509+
* @param outputPath The path object that will be assigned the chart data.
479510
*
480-
* @param dataSet
481511
* @return
482512
*/
483-
private Path generateFilledPath(ILineDataSet dataSet, XBounds bounds) {
513+
private void generateFilledPath(final ILineDataSet dataSet, final int startIndex, final int endIndex, final Path outputPath) {
484514

485-
float fillMin = dataSet.getFillFormatter().getFillLinePosition(dataSet, mChart);
486-
float phaseY = mAnimator.getPhaseY();
515+
final float fillMin = dataSet.getFillFormatter().getFillLinePosition(dataSet, mChart);
516+
final float phaseY = mAnimator.getPhaseY();
487517
final boolean isDrawSteppedEnabled = dataSet.getMode() == LineDataSet.Mode.STEPPED;
488518

489-
Path filled = mGenerateFilledPathBuffer;
519+
final Path filled = outputPath;
490520
filled.reset();
491-
Entry entry = dataSet.getEntryForIndex(bounds.min);
521+
522+
final Entry entry = dataSet.getEntryForIndex(startIndex);
492523

493524
filled.moveTo(entry.getX(), fillMin);
494525
filled.lineTo(entry.getX(), entry.getY() * phaseY);
495526

496527
// create a new path
497-
for (int x = bounds.min + 1; x <= bounds.range + bounds.min; x++) {
498-
499-
Entry e = dataSet.getEntryForIndex(x);
528+
Entry currentEntry = null;
529+
Entry previousEntry = null;
530+
for (int x = startIndex + 1 ; x <= endIndex ; x++) {
500531

501-
if (isDrawSteppedEnabled) {
502-
final Entry ePrev = dataSet.getEntryForIndex(x - 1);
503-
if (ePrev == null) continue;
532+
currentEntry = dataSet.getEntryForIndex(x);
504533

505-
filled.lineTo(e.getX(), ePrev.getY() * phaseY);
534+
if (isDrawSteppedEnabled && previousEntry != null) {
535+
filled.lineTo(currentEntry.getX(), previousEntry.getY() * phaseY);
506536
}
507537

508-
filled.lineTo(e.getX(), e.getY() * phaseY);
538+
filled.lineTo(currentEntry.getX(), currentEntry.getY() * phaseY);
539+
540+
previousEntry = currentEntry;
509541
}
510542

511543
// close up
512-
filled.lineTo(dataSet.getEntryForIndex(bounds.range + bounds.min).getX(), fillMin);
544+
if(currentEntry != null) {
545+
filled.lineTo(currentEntry.getX(), fillMin);
546+
}
547+
513548
filled.close();
514549

515-
return filled;
516550
}
517551

518552
@Override

0 commit comments

Comments
 (0)
X Tutup