Quantcast
Channel: Recent Threads — Xamarin Community Forums
Viewing all articles
Browse latest Browse all 204402

On which object and when we have to use dispose() ?

$
0
0

Hello,

If I understand well the architecture part of Xamarin, manage ressources is more complicated than in android native application, due to MCW.

My application use a lot of Bitmap image, and as I saw on the documentation, I have to help de GC by calling Dispose method or System.GC.Collect(). However, GC.Collect() is an heavy process and can't be call every time, therefore I prefer to use Dispose.

Now, my problem is I have some problem to identify the ressources that are not disposed and must have to be.

First step : Gridview of bitmap.

I display a gridview of bitmap.

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

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

            // Find controls
            productGridView = FindViewById<GridView>(Resource.Id.lstProducts);

            // wire up task click handler
            if (productGridView != null)
            {
                productGridView.ItemClick += (object sender, AdapterView.ItemClickEventArgs e) =>
                {
                    var productDetails = new Intent(this, typeof(DetailsProductActivity));
                    productDetails.PutExtra("ProductID", products[e.Position].Id);
                    StartActivity(productDetails);
                };
            }

        }


 protected override void OnResume()
        {
            base.OnResume();
            products = ProductManager.Instance.GetAllProducts();
            if (products.Count > 0)
            {
                productList = new Adapters.ProductListAdapter(this, products);
                productGridView.Adapter = productList;
                if (state != null)
                    productGridView.OnRestoreInstanceState(state);
            }

        }


        protected override void OnStop()
        {
            // Save ListView state
            state = productGridView.OnSaveInstanceState();
            base.OnStop();
        }

My list adaptator

    public class ProductListAdapter : BaseAdapter<Product>
    {
        protected Activity context = null;
        protected IList<Product> products = new List<Product>();

        public ProductListAdapter(Activity context, IList<Product> products)
            : base()
        {
            this.context = context;
            this.products = products;
        }


        public override Android.Views.View GetView(int position, Android.Views.View convertView, Android.Views.ViewGroup parent)
        {

            // Get our object for position
            var item = products[position];


            //Try to reuse convertView if it's not  null, otherwise inflate it from our item layout
            View view = convertView;
            if (view == null) {
                view = context.LayoutInflater.Inflate(Resource.Xml.productlistitem, null);

                // Personalize each item on the View.
                view.FindViewById<TextView>(Resource.Id.txtName).Text = AndroidTools.FormatText(item.Name, AndroidTools.TextFormatEnum.TITLECASE, 25);
                view.FindViewById<TextView>(Resource.Id.txtPrice).Text = item.Price.ToString() + "$";


                // Setting the image
                if (item.HasImage())
                {
                    byte[] smallImageByte = Convert.FromBase64String(item.SmallPic);
                    smallImageByte = Tools.Decompress(smallImageByte);
                    Bitmap smallPic = BitmapFactory.DecodeByteArray(smallImageByte, 0, smallImageByte.Length);
                    Drawable dr = new BitmapDrawable(smallPic);
                    smallPic.Dispose();
                    smallImageByte = null;
                    RelativeLayout r = view.FindViewById<RelativeLayout>(Resource.Id.smallPicProduct);
                    r.SetBackgroundDrawable(dr);
                    r.Dispose();
                    dr.Dispose();
                }
                else
                {
                    /* Android's ListView reuses list items when they aren't need anymore. 
                     * For this reason, you need to make sure all views that should change, will actually get changed.
                     */
                    RelativeLayout r = view.FindViewById<RelativeLayout>(Resource.Id.smallPicProduct);
                    r.SetBackgroundResource(Resource.Drawable.nopic_small);
                    r.Dispose();
                }

                //Finally return the view
              }
              return view;
        }


    }

Seems that it's ok, I put all the var to null and dispose all the bitmap ressources....

Second step : detail view of a product

    public class DetailsProductActivity : Activity
    {


        private Product product;
        private Bitmap bigPic;
        private ImageView pic;



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

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

            // Get the product
            int productID = Intent.GetIntExtra("ProductID", 0);
            if (productID > 0)
            {
                product = ProductManager.Instance.GetProduct(productID);
            }


            if (product != null)
            {
                FindViewById<TextView>(Resource.Id.txtName).Text = AndroidTools.FormatText(product.Name, AndroidTools.TextFormatEnum.TITLECASE, 50); ;
                FindViewById<TextView>(Resource.Id.txtPrice).Text = product.Price.ToString() + "$";
                FindViewById<TextView>(Resource.Id.txtDescription).Text = product.Description;
                FindViewById<TextView>(Resource.Id.txtDimensions).Text = product.Width + "x" + product.Height + "x" + product.Depth + product.DimensionsUnit;
                FindViewById<TextView>(Resource.Id.txtWeight).Text = product.Weight + product.WeightUnit;
                FindViewById<TextView>(Resource.Id.txtAddedTime).Text = Tools.UnixTimeStampToDateTime(product.AddedTime).ToString();



                pic = FindViewById<ImageView>(Resource.Id.bigPicProduct);

                if (product.HasImage())
                {
                    if (product.BigPic == null)
                    {
                        pic.SetImageResource(Resource.Drawable.loading);
                        suscribe();
                        ProductManager.Instance.GetBigPicProductAsync(product);
                    }
                    else
                    {
                        byte[] bigImageByte = Convert.FromBase64String(product.BigPic);
                        bigImageByte = Tools.Decompress(bigImageByte);
                        bigPic = BitmapFactory.DecodeByteArray(bigImageByte, 0, bigImageByte.Length);
                        pic.SetImageBitmap(bigPic);
                        bigImageByte = null;
                        bigPic.Dispose();

                    }

                }
            }

        }





        protected override void OnDestroy()
        {
            pic.Dispose();
            base.OnDestroy();
        }

        #endregion



        private void suscribe()
        {
            ProductManager.Instance.RequestEnded += loadingBigPicFinished;
        }


        private void unsuscribe()
        {
            ProductManager.Instance.RequestEnded -= loadingBigPicFinished;
        }



        private void loadingBigPicFinished(Boolean result, Exception e)
        {
            unsuscribe();

            if (result)
            {

                product = ProductManager.Instance.GetProduct(product.Id);
                byte[] bigImageByte = Convert.FromBase64String(product.BigPic);
                bigImageByte = Tools.Decompress(bigImageByte);
                bigPic = BitmapFactory.DecodeByteArray(bigImageByte, 0, bigImageByte.Length);
                bigImageByte = null;

                RunOnUiThread(() =>
                {
                    pic.SetImageBitmap(bigPic);
                    bigPic.Dispose();
                }

                );

            }
            else
            {
                RunOnUiThread(() => AndroidTools.ShowDialog(this, "Error", e.Message, Finish));
            }
        }



    }
}

Same remarks. But after some browsing, I have a out of memory. So seems that one heavy ressources is not Dispose()ed....

So my question is :

  • Is enough to "dispose" bitmap ? Or We have to dispose also other ressources ?
  • If is enough, I really don't understand how I can have a out of memory ...

Huge thanks for who will help me because I'm almost resigned to use System.GC.Collect() ....


Viewing all articles
Browse latest Browse all 204402

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>