Cheesebaron / SlidingMenuSharp

A direct port of https://github.com/jfeinstein10/SlidingMenu to C# to work with Xamarin.Android
Apache License 2.0
54 stars 39 forks source link

System.ObjectDisposedException: Cannot access a disposed object. #20

Open ovsk opened 7 years ago

ovsk commented 7 years ago

I am using this library developed by @Cheesebaron from past years in my project it never gave me any issues. Currently i am upgrading my app to target API level 24 and its crashing occasionally without any proper reason. Below is the error log, kindly help, it is very important

[MonoDroid] UNHANDLED EXCEPTION: [MonoDroid] System.ObjectDisposedException: Cannot access a disposed object. [MonoDroid] Object name: 'Android.Widget.Scroller'. [MonoDroid] at Java.Interop.JniPeerMembers.AssertSelf (Java.Interop.IJavaPeerable self) [0x00030] in /Users/builder/data/lanes/3511/501e63ce/source/Java.Interop/src/Java.Interop/Java.Interop/JniPeerMembers.cs:153 [MonoDroid] at Java.Interop.JniPeerMembers+JniInstanceMethods.InvokeNonvirtualBooleanMethod (System.String encodedMember, Java.Interop.IJavaPeerable self, Java.Interop.JniArgumentValue* parameters) [0x00002] in /Users/builder/data/lanes/3511/501e63ce/source/Java.Interop/src/Java.Interop/Java.Interop/JniPeerMembers.JniInstanceMethods_Invoke.cs:73 [MonoDroid] at Android.Widget.Scroller.get_IsFinished () [0x00000] in /Users/builder/data/lanes/3511/501e63ce/source/monodroid/src/Mono.Android/platforms/android-24/src/generated/Android.Widget.Scroller.cs:218 [MonoDroid] at SlidingMenuSharp.CustomViewAbove.ComputeScroll () [0x00001] in <644015490a8d4e6a9989999589722a33>:0 [MonoDroid] at Android.Views.View.n_ComputeScroll (System.IntPtr jnienv, System.IntPtr nativethis) [0x00009] in /Users/builder/data/lanes/3511/501e63ce/source/monodroid/src/Mono.Android/platforms/android-24/src/generated/Android.Views.View.cs:11484 [MonoDroid] at (wrapper dynamic-method) System.Object:0d8f5eb4-78f9-44d3-b8a3-f9afc5137b0a (intptr,intptr) [Mono] DllImport searching in: 'Internal' ('(null)'). [Mono] Searching for 'java_interop_jnienv_throw'. [Mono] Probing 'java_interop_jnienv_throw'. [Mono] Found as 'java_interop_jnienv_throw'.

Cheesebaron commented 7 years ago

When does it crash? This exception indicates that the view has been disposed for some reason.

ovsk commented 7 years ago

I have added two sliding menu's on both sides left and right side of main screen. From main screen i am moving to setting screen and from there another sub-setting screen where i am calling async method to fetch data from internet and when moving back to main screen from settings page, labels on main screen gets updated with newly fetched data.

After data fetch is complete, and i press back button twice to reach main screen, error is thrown. Sometimes it works perfectly and i see changed data on main screen, but sometimes on 2nd back button press above error is thrown and app crashes.

mjrmurray commented 7 years ago

I'm having the same issue. Same error and stack trace. I feel like this is happening after garbage collection runs, but i'm not sure why. This is a huge problem for our app. If i fix it, i'll post the solution, but as of now i have no idea what is going on.

mjrmurray commented 7 years ago

So i have no idea why, but the CustomViewAbove class disposes it's Scroller (Android.Widget.Scroller) too early. It was the only part of this class that was being disposed and subsequently was throwing the ObjectDisposedException mentioned above by ovsk. I still can't find the root cause, but I was able to work around this by adding the following code to my CustomViewAbove.cs file:

In public overrride void ComputeScroll() i am re-initializing the class because after garbage collection runs, as soon as !_scroller.IsFinished is called, the application crashes. I was never able to actually catch the exception in a try catch block either. Also i was encountering issues with Invalidate so i commented it out.

    public override void ComputeScroll()
    {
        InitCustomViewAbove(); 

        if (!_scroller.IsFinished)
           {
                if (_scroller.ComputeScrollOffset())
                {
                    var oldX = ScrollX;
                    var oldY = ScrollY;
                    var x = _scroller.CurrX;
                    var y = _scroller.CurrY;

                    if (oldX != x || oldY != y)
                    {
                        ScrollTo(x, y);
                        OnPageScrolled(x);
                    }

                    //Invalidate();
                    return;
                }
            }
            CompleteScroll();        
          }

Once this code was added i started seeing rendering problems with action events. In order to force these actions to respond, i had to call CompleteScroll() again inside SmoothScrollTo function and comment out invalidate() again. These two changes "fixed" my issues. Root cause is still unknown.

    void SmoothScrollTo(int x, int y, int velocity = 0)
    {

        if (ChildCount == 0)
        {
            ScrollingCacheEnabled = false;
            return;
        }

        var sx = ScrollX;
        var sy = ScrollY;
        var dx = x - sx;
        var dy = y - sy;
        if (dx == 0 && dy == 0)
        {
            CompleteScroll();
            if (IsMenuOpen)
            {
                if (null != Opened)
                    Opened(this, EventArgs.Empty);
            }
            else
            {
                if (null != Closed)
                    Closed(this, EventArgs.Empty);
            }
            return;
        }

        ScrollingCacheEnabled = true;
        _scrolling = true;

        var width = BehindWidth;
        var halfWidth = width / 2;
        var distanceRatio = Math.Min(1f, 1.0f * Math.Abs(dx) / width);
        var distance = halfWidth + halfWidth * DistanceInfluenceForSnapDuration(distanceRatio);
        int duration;
        velocity = Math.Abs(velocity);
        if (velocity > 0)
            duration = (int)(4 * Math.Round(1000 * Math.Abs(distance / velocity)));
        else
        {
            var pageDelta = (float) Math.Abs(dx) / width;
            duration = (int) ((pageDelta + 1) * 100);
        }
        duration = Math.Min(duration, MaxSettleDuration);

        _scroller.StartScroll(sx, sy, dx, dy, duration);
        CompleteScroll();
        //Invalidate();
       }
lexboss777 commented 7 years ago

I confirm that there is an issue. Finally I stopped using this library at 12 february of 2017. I think maybe something wrong happens with xamarin peer objects. Maybe java-side object disposed regardless there is alive mono-object.

Now I am facing same on port to C# of https://github.com/matabii/scale-imageview-android Also I found if to run this code while Activity is running it causes to issue come more earlier:

System.Threading.Tasks.Task MemoryEater ()
{
    return System.Threading.Tasks.Task.Run (async () => {

        while (true) {
            byte [] f = new byte [1000 * 1000 * 5];
            await System.Threading.Tasks.Task.Delay (200);
            f = null;
        }
    });
}
lexboss777 commented 7 years ago

It seems to me that problem comes from the mono's new design of the GC Bridge - Tarjan.

To switch bridge implementation to the old one try adding a file to your project, like environment.txt, with build option set to AndroidEnvironment with following content:

MONO_GC_PARAMS=bridge-implementation=old

JatinKinra commented 7 years ago

Does this issue got resolved ? I am still facing this issue, and it is a major roadblock. And @lexboss93 , can u please mention how to set the build option to AndroidEnvironment in Xamarin.Android project.

lexboss777 commented 7 years ago

@JatinKinra, not resolved yet. You can trace bug-report here. Setting build option: screen shot 2017-08-17 at 10 19 00 You can check the source-code of the project here. You better set the bridge-implementation to "new" instead of "old". Read more.

ajaynarang commented 6 years ago

@lexboss93 - I checked the bug report link above and seems like it hasn't been resolved yet. I am also facing the same issue do you see any workaround for this?