简体   繁体   中英

Clearing image stream out of memory

So, I have a quite simple test project. A timer that every even iteration spawns a view and every odd iteration kills the view. The view itself is a RelativeLayout with an image. What I want to do is to be able to let this time run indefinitely without havig memory issues. Thing is, I don't know how to truly clear the image stream I use to create the bitmap out of the memory. I am recycling the bitmap when I don't need it anymore but that's not enough. The code is in C# (Xamarin), but java answers also help.

protected override void OnCreate (Bundle bundle)
    {
        base.OnCreate (bundle);

        // Set our view from the "main" layout resource
        SetContentView (Resource.Layout.Main);

        RelativeLayout mainView = new RelativeLayout (this);
        this.AddContentView(mainView, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MatchParent, ViewGroup.LayoutParams.MatchParent));

        ...

        int i = 0;
        System.Timers.Timer t = new System.Timers.Timer (100);
        t.Elapsed += delegate(object sender, System.Timers.ElapsedEventArgs e) {
            RunOnUiThread(delegate() {
                if(i++ % 2 == 0){
                    tmpView tView = new tmpView(this);
                    mainView.AddView(tView, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MatchParent, ViewGroup.LayoutParams.MatchParent));
                }else{
                    ((tmpView)mainView.GetChildAt(0)).dispose();
                    mainView.RemoveAllViews();
                }
            });

        };
        t.AutoReset = true;
        t.Start ();

    }

    private class tmpView:RelativeLayout{
        ImageView img;
        Android.Graphics.Bitmap bmp;
        public tmpView(Context cntx):base(cntx){
            SetBackgroundColor(new Android.Graphics.Color(200, 0, 0, 200));
            System.IO.Stream imgStream = Application.Context.Assets.Open ("backgroundLeft.png");
            img = new ImageView(cntx);
            bmp = Android.Graphics.BitmapFactory.DecodeStream (imgStream);
            img.SetImageBitmap(bmp);
            //bmp.Recycle();
            imgStream.Close();
            RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MatchParent, 500);
            lp.TopMargin = 150;
            this.AddView(img, lp);
        }

        public void dispose(){
            bmp.Recycle ();
            img.SetImageDrawable (null);
        }
    }

Also, the reason why I say that the image stream is what's causing the memory leaks is because I'm actually able to make this time run the whole day. I have to add GC calls right after the imgStream.Close(); ( GC.SuppressFinalize(imgStream); and GC.Collect(); ). But calling the GC will cause noticeable lag, and besides, I dont want to wipe everything, just the stream. Also, this is running on a device.

Ty, Axel

I'd recommend you check this small talk about memory on Android:

https://realm.io/news/droidcon-ricau-memory-leaks-leakcanary/

It's pretty interesting, and should explain why your image is retained in a context not cleaned by the garbage collector.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM