Monodroid GREF проблема наилучшей практики? - PullRequest
1 голос
/ 16 сентября 2011

У меня есть следующий тестовый код (на основе стандартного монодроида HelloWorld)

namespace TestGREF
{
    [Activity (Label = "TestGREF", MainLauncher = true)]
    public class Activity1 : Activity
    {
        int count = 1;      
        protected override void OnCreate (Bundle bundle)
        {
            base.OnCreate (bundle);
            SetContentView (Resource.Layout.Main);
            Button button = FindViewById<Button> (Resource.Id.myButton);

            button.Click += delegate {
                button.Text = string.Format ("{0} clicks!", count++); 
                for(int i=0;i<10000;i++){
                    new Java.Lang.Object(new System.IntPtr(i));
                    //...some stuff here. Instead of Java.Lang.Object may be
                    //something much more useful.
                }

                //If uncomment here, looks ok
                //GC.Collect(GC.MaxGeneration, GCCollectionMode.Forced);
            };
        }
    }
}

Если я нажимаю кнопку 5-6 раз, приложение вылетает.

Я знаю, что это происходит из-за ограничения глобальных ссылок (GREF) (описано здесь , раздел «Неожиданные исключения NullReferenceExceptions»). Вопрос: что с этим делать? Какова лучшая практика? Если возможно, с примером кода, пожалуйста

Если раскомментировать вызов GC.Collect (), все кажется работающим, но слишком частый вызов GC слишком дорог для производительности. Другой популярный дизайн - поставить цикл операторов, но это не всегда является возможной причиной логики программы.

Есть еще идеи?

Ответы [ 3 ]

2 голосов
/ 26 января 2012
for(int i=0;i<10000;i++){
    var obj = new Java.Lang.Object(new System.IntPtr(i));

    //...some stuff here. Instead of Java.Lang.Object may be
    //something much more useful.

    obj.Dispose(); //Deletes an object and GREF too. 
    //Cannot be used if object is still used in dalvik VM
}

Если вы не можете использовать Dispose () (например, неуправляемый объект является частью макета, который будет использоваться под Android, но не кодом C #), используйте GC.Collect () с умом. GC.Collect () убивает все GREF для переменных, которые не используются Mono Environment и находятся вне текущей области.

2 голосов
/ 16 сентября 2011

Вам необходимо освободить все неуправляемые объекты, когда они больше не нужны. Все классы, которые наследуются от Android.Runtime.IJavaObject, также наследуют IDisposable, поэтому вам нужно их утилизировать.

Вот часть моего проекта

private Spinner _spType;
private ArrayAdapter _arrayAdapter;

protected override void OnCreate(Android.OS.Bundle savedInstanceState)
{
  base.OnCreate(savedInstanceState);
  _spType = FindViewById<Spinner>(Resource.Id.spinnerType);
  _arrayAdapter = new ArrayAdapter(this, Android.Resource.Layout.SimpleSpinnerItem, new[] {"1","2","3","4","5"});
  _spType.Adapter = _arrayAdapter;
}

public override void Finish()
{
    if (_spType != null)
        _spType.Dispose();
    if (_arrayAdapter != null)
        _arrayAdapter.Dispose();
    base.Finish();
}
0 голосов
/ 20 сентября 2011

Вот статья о ГХ и управлении памятью в монодроиде.Это может быть полезно для вас http://docs.xamarin.com/android/advanced_topics/garbage_collection

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...