PhilJay / MPAndroidChart

A powerful 🚀 Android chart view / graph view library, supporting line- bar- pie- radar- bubble- and candlestick charts as well as scaling, panning and animations.
Other
37.59k stars 9.02k forks source link

MoveViewJob.pool is memory leak #2238

Open ChuuMong opened 8 years ago

ChuuMong commented 8 years ago

MoveVIewJab.java

in a

private static ObjectPool<MoveViewJob> pool;

occurs memory leck.

BaN4NaJ0e commented 8 years ago

Leak Canary detected the same problem in my app. Here is an export from the leak canary report:

In de.example.base.prod:TODO:1.

I hope this helps to fix the issue.

Alkisum commented 7 years ago

Leak Canary detects the same memory leak in my app. It occurs since I updated the library from version v2.2.5 to v3.0.1:

* de.myapp.device.DeviceActivity has leaked:
* GC ROOT static com.github.mikephil.charting.jobs.MoveViewJob.pool
* references com.github.mikephil.charting.utils.ObjectPool.objects
* references array java.lang.Object[].[2]
* references com.github.mikephil.charting.jobs.MoveViewJob.view
* references com.github.mikephil.charting.charts.LineChart.mContext
* leaks de.myapp.device.DeviceActivity instance
Diederikjh commented 7 years ago

I got this leak when I called LineChart.centerViewTo(). It spawns a MoveViewJob that is added to the static pool member mentioned in the original post. This job contains a reference to the (chart)view and because of how my event handlers were tied up caused my activity to leak.

Hacky fix for my scenario is to call MoveViewJob.getInstance(null, 0, 0, null, null); on the fragment's onPause(). (The fragment that contains the chart view.)

This call nullifies the view reference on the pool object, and makes the view garbage collectable.

recoverrelax commented 7 years ago

Same here. MoveViewJob.getInstance(null, 0f, 0f, null, null) called in activity onDestroy fixed the leak. Any official solution for this?

recoverrelax commented 7 years ago

any news on this? at least an official workaround until it is fixed. Thanks in advanced

FengQing123 commented 6 years ago

i write MoveViewJob.getInstance(null, 0f, 0f, null, null) in activity onDestroy,and it also leak , i don't know how to fix it?

almic commented 6 years ago

I can confirm that the animation pools were not properly created. I'm working through a massive refactor/ documentation update now and I believe I've fixed the issue already, but the commit is still a bit into the future. I noticed a few cases already where these objects were NEVER recycled, despite that being the intention of the ObjectPool class, to allow these animations to be easily reusable.

Specifically, I believe this line is the cause of the problem, Android Studio even reports a warning on it:

Line 49

this.recycleInstance(this);

The problem is that it uses this.recycleInstance(this) instead of what ZoomJob uses, a plain static call to recycleInstance(this)

I can also confirm that these objects aren't super expensive, so perhaps gutting the ObjectPool and just creating these objects locally could solve the problem, as they are guaranteed to be garbage collected if only being created in local scopes and not permanently stored with activities or other objects. But I'll leave that option up for debate.

haiithust commented 6 years ago

any body find the solution? I have same problem, I put barchart in recyclerview and always move to item zero, it's work but cause memory leak. I treat using

                float[] pts = {-1f, 0f};
                Transformer transformer = chart.getTransformer(YAxis.AxisDependency.LEFT);
                ViewPortHandler viewPortHandler = chart.getViewPortHandler();
                transformer.pointValuesToPixel(pts);
                viewPortHandler.centerViewPort(pts, chart);

when I scroll barchart it's delay 3, 4 seconds to scroll to zero.

po1arbear commented 6 years ago

call MoveViewJob.getInstance(null, 0f, 0f, null, null) onDestory doesn't work in my Activity,anyone solve this problem?

goraga1 commented 6 years ago

If you use RecyclerView you can write


     @Override
    public void onDetachedFromRecyclerView(@NonNull RecyclerView recyclerView) {
        MoveViewJob.getInstance(null, 0, 0, null, null);
    }
ZaydelEduard commented 5 years ago

Call on the onDestroy() for activity Call on the onDestroyView() for fragment

private fun fixChartMemoryLeaks() {
        // Fix https://github.com/PhilJay/MPAndroidChart/issues/2238
        val moveViewJobPoll = MoveViewJob::class.java.getDeclaredField("pool")
        moveViewJobPoll.isAccessible = true
        moveViewJobPoll.set(null, ObjectPool.create(2, MoveViewJob(null, 0f, 0f, null, null)))

        // the same issue with ZoomJob
        val zoomViewJobPoll = ZoomJob::class.java.getDeclaredField("pool")
        zoomViewJobPoll.isAccessible = true
        zoomViewJobPoll.set(null, ObjectPool.create(2, ZoomJob(null, 0f, 0f, 0f, 0f, null, null, null)))
}
pengxinaglin commented 4 years ago

在 MoveViewJob 类中加以下代码

public static void recycleInstance(MoveViewJob instance) { instance.mViewPortHandler = null; instance.mTrans = null; instance.view = null; pool.recycle(instance); }

HolenZhou commented 2 years ago

这样只能修改源码了

Shekhanzai commented 2 weeks ago

the only solution i found is

try { Field poolField = MoveViewJob.class.getDeclaredField("pool"); poolField.setAccessible(true); ObjectPool newPool = ObjectPool.create(2, new MoveViewJob(null, 0, 0, null, null)); newPool.setReplenishPercentage(0.5f); poolField.set(null, newPool); } catch (Exception e) { e.printStackTrace(); }