From b7fe79ce107d5f243d429645d885435e3a738b0c Mon Sep 17 00:00:00 2001 From: agabriel Date: Mon, 3 Jan 2022 16:27:08 -0300 Subject: [PATCH 1/2] changed mImageCache from HashMap to WeakHashMap to avoid OOM Moved DataSetImageCache.init from a method to a constructor. The main idea is verify the content of the color in array instead of only the length. I met one use case that I needed to use different colors from dots. So I used the method setCircleColors, but when I call drawCircle it doesnt works because the length of the circle array is not change, only the content is changed. --- .../charting/renderer/LineChartRenderer.java | 41 +++++++++---------- 1 file changed, 19 insertions(+), 22 deletions(-) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineChartRenderer.java index a86c16f76b..93dd207c74 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineChartRenderer.java @@ -26,6 +26,7 @@ import java.lang.ref.WeakReference; import java.util.HashMap; import java.util.List; +import java.util.WeakHashMap; public class LineChartRenderer extends LineRadarRenderer { @@ -611,7 +612,7 @@ public void drawExtras(Canvas c) { /** * cache for the circle bitmaps of all datasets */ - private HashMap mImageCaches = new HashMap<>(); + private WeakHashMap mImageCaches = new WeakHashMap<>(); /** * buffer for drawing the circles @@ -656,16 +657,11 @@ protected void drawCircles(Canvas c) { if (mImageCaches.containsKey(dataSet)) { imageCache = mImageCaches.get(dataSet); } else { - imageCache = new DataSetImageCache(); + imageCache = new DataSetImageCache(dataSet); mImageCaches.put(dataSet, imageCache); } - boolean changeRequired = imageCache.init(dataSet); - - // only fill the cache with new bitmaps if a change is required - if (changeRequired) { - imageCache.fill(dataSet, drawCircleHole, drawTransparentCircleHole); - } + imageCache.fill(dataSet, drawCircleHole, drawTransparentCircleHole); int boundsRangeCount = mXBounds.range + mXBounds.min; @@ -767,27 +763,16 @@ private class DataSetImageCache { private Path mCirclePathBuffer = new Path(); private Bitmap[] circleBitmaps; + private int[] circleColors; - /** - * Sets up the cache, returns true if a change of cache was required. - * - * @param set - * @return - */ - protected boolean init(ILineDataSet set) { - + DataSetImageCache(ILineDataSet set) { int size = set.getCircleColorCount(); - boolean changeRequired = false; if (circleBitmaps == null) { circleBitmaps = new Bitmap[size]; - changeRequired = true; } else if (circleBitmaps.length != size) { circleBitmaps = new Bitmap[size]; - changeRequired = true; } - - return changeRequired; } /** @@ -804,7 +789,8 @@ protected void fill(ILineDataSet set, boolean drawCircleHole, boolean drawTransp float circleHoleRadius = set.getCircleHoleRadius(); for (int i = 0; i < colorCount; i++) { - + if (!changeRequired(set, colorCount, i)) + continue; Bitmap.Config conf = Bitmap.Config.ARGB_4444; Bitmap circleBitmap = Bitmap.createBitmap((int) (circleRadius * 2.1), (int) (circleRadius * 2.1), conf); @@ -850,6 +836,17 @@ protected void fill(ILineDataSet set, boolean drawCircleHole, boolean drawTransp } } + private boolean changeRequired(ILineDataSet set, int colorCount, int i) { + if (circleColors == null || circleColors.length != colorCount) { + circleColors = new int[colorCount]; + } + if (circleColors[i] == set.getCircleColor(i)) { + return true; + } + circleColors[i] = set.getCircleColor(i); + return false; + } + /** * Returns the cached Bitmap at the given index. * From e603d8ffbcb37b28dd33d5e175ff063d93fbe0ba Mon Sep 17 00:00:00 2001 From: agabriel Date: Mon, 3 Jan 2022 18:25:53 -0300 Subject: [PATCH 2/2] Created an example for toggle colors from circles on lineChart --- .../mpchartexample/LineChartActivity1.java | 24 +++++++++++++++-- MPChartExample/src/main/res/values/colors.xml | 5 ++++ .../charting/renderer/LineChartRenderer.java | 27 ++++++++++--------- 3 files changed, 41 insertions(+), 15 deletions(-) create mode 100644 MPChartExample/src/main/res/values/colors.xml diff --git a/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java index dd43b056eb..d9decf652d 100644 --- a/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java +++ b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java @@ -442,13 +442,33 @@ public void onStopTrackingTouch(SeekBar seekBar) {} @Override public void onValueSelected(Entry e, Highlight h) { + toggleCirclesColorOnGraphSelection(true); Log.i("Entry selected", e.toString()); - Log.i("LOW HIGH", "low: " + chart.getLowestVisibleX() + ", high: " + chart.getHighestVisibleX()); - Log.i("MIN MAX", "xMin: " + chart.getXChartMin() + ", xMax: " + chart.getXChartMax() + ", yMin: " + chart.getYChartMin() + ", yMax: " + chart.getYChartMax()); + Log.i("LOW HIGH", + "low: " + chart.getLowestVisibleX() + ", high: " + chart.getHighestVisibleX()); + Log.i("MIN MAX", + "xMin: " + chart.getXChartMin() + ", xMax: " + chart.getXChartMax() + ", yMin: " + + chart.getYChartMin() + ", yMax: " + chart.getYChartMax()); } @Override public void onNothingSelected() { + toggleCirclesColorOnGraphSelection(false); Log.i("Nothing selected", "Nothing selected."); } + + private void toggleCirclesColorOnGraphSelection(boolean isSelected) { + List dataSets = chart.getData().getDataSets(); + for (int i = 0; i < dataSets.size(); i++) { + ILineDataSet dataSet = dataSets.get(i); + if (dataSet instanceof LineDataSet) { + List colors = new ArrayList<>(); + for (int i1 = 0; i1 < dataSet.getEntryCount(); i1++) { + colors.add(getResources().getColor(isSelected ? R.color.gray : R.color.black)); + } + ((LineDataSet) dataSet).setCircleColors(colors); + } + } + chart.notifyDataSetChanged(); + } } diff --git a/MPChartExample/src/main/res/values/colors.xml b/MPChartExample/src/main/res/values/colors.xml new file mode 100644 index 0000000000..249a715763 --- /dev/null +++ b/MPChartExample/src/main/res/values/colors.xml @@ -0,0 +1,5 @@ + + + #efefef + #000 + \ No newline at end of file diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineChartRenderer.java index 93dd207c74..458f899370 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineChartRenderer.java @@ -657,7 +657,7 @@ protected void drawCircles(Canvas c) { if (mImageCaches.containsKey(dataSet)) { imageCache = mImageCaches.get(dataSet); } else { - imageCache = new DataSetImageCache(dataSet); + imageCache = new DataSetImageCache(); mImageCaches.put(dataSet, imageCache); } @@ -765,16 +765,6 @@ private class DataSetImageCache { private Bitmap[] circleBitmaps; private int[] circleColors; - DataSetImageCache(ILineDataSet set) { - int size = set.getCircleColorCount(); - - if (circleBitmaps == null) { - circleBitmaps = new Bitmap[size]; - } else if (circleBitmaps.length != size) { - circleBitmaps = new Bitmap[size]; - } - } - /** * Fills the cache with bitmaps for the given dataset. * @@ -782,8 +772,9 @@ private class DataSetImageCache { * @param drawCircleHole * @param drawTransparentCircleHole */ - protected void fill(ILineDataSet set, boolean drawCircleHole, boolean drawTransparentCircleHole) { - + protected void fill(ILineDataSet set, boolean drawCircleHole, + boolean drawTransparentCircleHole) { + init(set); int colorCount = set.getCircleColorCount(); float circleRadius = set.getCircleRadius(); float circleHoleRadius = set.getCircleHoleRadius(); @@ -836,6 +827,16 @@ protected void fill(ILineDataSet set, boolean drawCircleHole, boolean drawTransp } } + private void init(ILineDataSet set) { + int size = set.getCircleColorCount(); + + if (circleBitmaps == null) { + circleBitmaps = new Bitmap[size]; + } else if (circleBitmaps.length != size) { + circleBitmaps = new Bitmap[size]; + } + } + private boolean changeRequired(ILineDataSet set, int colorCount, int i) { if (circleColors == null || circleColors.length != colorCount) { circleColors = new int[colorCount];