2011-09-16 4 views
1

je le code de test suivant (basé sur HelloWorld standard MonoDroid)Problème Monodroid GREF problème?

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); 
      }; 
     } 
    } 
} 

Si je clique sur le bouton 5-6 fois, application se bloque.

Je sais que cela se produit en raison de la limite de références globales (GREF) (décrit here, section "Unexpected NullReferenceExceptions"). La question est: que faire avec? Quelle est la meilleure pratique? Si possible, avec l'exemple de code s'il vous plaît

Si vous ne commentez pas l'appel GC.Collect(), tout semble fonctionner, mais l'appel GC trop souvent est trop exprès pour les performances. Une autre conception populaire est de mettre une nouvelle déclaration de boucle, mais ce n'est pas toujours possible cause de la logique du programme.

D'autres idées?

+0

Merci de votre aide à tous, mais ce n'est toujours pas ce que je voulais vraiment. J'ai étudié le problème un peu plus en profondeur, et il semble que je voulais quelque chose d'impossible (= – PVoLan

Répondre

2
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 
} 

Si vous ne pouvez pas utiliser Dispose() (par exemple, un objet non géré est une partie de mise en page, qui sera utilisé par Android admis- sion mais pas par C Code de #), l'utilisation GC.Collect() judicieusement. GC.Collect() tue tous les fichiers GREF en variables, qui sont hors d'usage par Mono Environment et hors de la portée actuelle.

2

Vous devez libérer tous les objets non gérés lorsqu'ils ne sont plus nécessaires. Toutes les classes qui héritent de Android.Runtime.IJavaObject héritent également de IDisposable, vous devez donc les disposer.

Voici une partie de mon projet

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(); 
}