2017-12-08 9 views
0

私はFormsアプリケーションの中核と思われるメモリリーク(またはリーク)を調べています。AndroidのXamarin.Formsのリークは、単純なプッシュ/ポップのページですか?

私たちはFreshMvvmを使用していますが、以前はPages/PageModelsがガベージコレクションされていないためにかなりのリークがありました。 Michael Ridland(FreshMvvm)の著者)はこれを修正しました。これは素晴らしいことです。

しかし、GC.GetTotalMemory()が返す数値は着実に増加しています。それはです減少しますが、一般的な傾向は上向きです。

私はちょうど別のページをプッシュするプレーンページを持っているので、私は最初に戻ってポップアップすることができます。

これを行うと、GC.GetTotalMemory()が一般的に毎回2K〜4Kずつ増加しています。これは強制的にGC.Collect()を呼び出した後です。

私たちはXamarin.Forms 2.3.4.270を実行しています。これはかなり古いと知っていますが、新しいフォームのバグを導入したくないので、アップグレードしたくありません。しかし、私は2.5.0.121934に実験的にアップグレードしようとしましたが、私は同じ動作を見ています(このバージョンで動作するアプリの側面も停止しています)。

Profilerを使用しないと、犯人を見つけるために使用できる調査手法はありますか?

私の次のステップは、ますます引き離すことです!

答えて

0

私はXamarin.Formsのメモリリークと、過去に同様の問題が発生しましたし、ビュー/ページが、このクラスが作成された犯人何であったか理解を助けるために:

public static class Refs 
{ 
    private static readonly List<WeakReference> _refs = new List<WeakReference>(); 

    public static readonly BindableProperty IsWatchedProperty = BindableProperty.CreateAttached("IsWatched", typeof(bool), typeof(Refs), false, propertyChanged: OnIsWatchedChanged); 

    public static bool GetIsWatched(BindableObject obj) 
    { 
     return (bool)obj.GetValue(IsWatchedProperty); 
    } 

    public static void SetIsWatched(BindableObject obj, bool value) 
    { 
     obj.SetValue(IsWatchedProperty, value); 
    } 

    private static void OnIsWatchedChanged(BindableObject bindable, object oldValue, object newValue) 
    { 
     AddRef(bindable); 
    } 

    public async static void AddRef(object p) 
    { 
     GC.Collect(); 
     await Task.Delay(100); 
     GC.Collect(); 

     _refs.Add(new WeakReference(p)); 
     foreach (var @ref in _refs) 
     { 
      if (@ref.IsAlive) 
      { 
       var obj = @ref.Target; 
       Debug.WriteLine("IsAlive: " + obj.GetType().Name); 
      } 
      else 
      { 
       Debug.WriteLine("IsAlive: False"); 
      } 
     } 
     Debug.WriteLine("---------------"); 
    } 
} 

次にあなたが使用することができ、それを使用しますページxamlまたはコードのIsWatchedプロパティは、InitializeComponent();の後にRefs.AddRef(this);を実行して、ページを数回移動するだけです。もしそれがgc'edされていれば、コンソールはIsAliveを出力しなければなりません:もしそうでなければFalseをタイプします。

多くの場合、私たちが持っていたリークは、BindingContextをクリアしたり、ページを離れるときにnullに設定したりすることで修正されました。

protected override void OnParentSet() 
{ 
    base.OnParentSet(); 

    if (Parent == null) 
    { 
     BindingContext = null; 
    } 
} 
関連する問題