0

Spark Comboボックスに関連する単純で再現可能なメモリリークがありますが、SDKのバグではなく、間違っていることが原因であると確信しています。

// Application.mxml
<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009" 
               xmlns:s="library://ns.adobe.com/flex/spark" 
               xmlns:mx="library://ns.adobe.com/flex/mx">
    <s:layout>
        <s:VerticalLayout />
    </s:layout>
    <fx:Script>
        <![CDATA[
            import mx.events.FlexEvent;

            private var hasElement:Boolean;
            protected function toggleContainer():void
            {
                if (hasElement)
                {
                    button.setFocus();
                    comboBoxContainer.removeAllElements();
                    hasElement = false;
                } else {
                    var vew:ComboBoxView = new ComboBoxView();
                    comboBoxContainer.addElement(vew);
                    hasElement = true;
                }
            }
        ]]>
    </fx:Script>
    <s:Button id="button" label="Add container" click="toggleContainer()"  />
    <s:Group id="comboBoxContainer" />
</s:Application>


// ComboBoxView.mxml

<?xml version="1.0" encoding="utf-8"?>
<s:VGroup xmlns:fx="http://ns.adobe.com/mxml/2009" 
         xmlns:s="library://ns.adobe.com/flex/spark" 
         xmlns:mx="library://ns.adobe.com/flex/mx"
         >
    <s:ComboBox />
</s:VGroup>

Flex 4.1に対してコンパイルすると、メモリリークが発生し、ComboBoxへの参照が長引くためにComboBoxViewがGCされることはありません。

プロファイラーからの出力は次のとおりです。 ここに画像の説明を入力してください

再現する手順:

  • Application.mxmlおよびを使用してプロジェクトを作成するComboBoxView.mxml
  • Flex4.1を使用してプロジェクトをコンパイルします
  • プロファイラーを使用してApplication.mxmlを起動します
  • メモリスナップショットを作成する
  • ボタンをクリックして、ビューをステージに追加します
  • ボタンをもう一度クリックして、ステージからビューを削除します
  • ガベージコレクターを実行します
  • 別のメモリスナップショットを作成する
  • 2つのメモリスナップショットの間に残っているオブジェクトを表示する

注-これは、アプリケーションがFlexHeroに対してコンパイルされている場合は発生しません。

これはバグのように見えますが、ComboBoxにメモリリークがあるとは信じられません。確かに、4.1が出荷される前にこれは修正されていたでしょうか。

私はここで何が間違っているのですか?ビューがGCされないのはなぜですか?

更新 私はこれについてさらに調査を行いましたが、問題はComboBoxSkinが使用するRichEditableTextコンポーネントの問題にあると考えています。詳細はこちらをご覧ください: Sparkメモリリーク

4

2 に答える 2

1

http://www.iampj.com/search/label/combobox%20memory%20leak

私はflex 3で同様の問題を抱えています

于 2011-06-07T12:35:36.487 に答える
0

MXML は、バックグラウンドで何が行われているかを正確に知ることができないため、注意が必要な場合があります (-keep 属性と外観を使用しない限り)。

しかし、ComboBox 参照を決して無効にしないように見えます。コンテナの子を削除することは、そのインスタンスをメモリから削除することと同じではありません。たとえば、Flextras Calendar コンポーネントでは、月が変わると表示から日を削除することは珍しくありません。月によっては、28 日から 31 日表示される場合があります。ただし、1 か月が 31 日で、30 日の月に切り替えた場合、これらの余分な日のレンダラーを無効にすることはありません。それらを「unusedDays」配列にキャッシュするだけで、次の準備が整います。月が変わる時間。

ListBase クラスも同様で、Flex 4 には useVirtualLayout という名前のプロパティがあり、これをメモリに保持する方法を制御できると思います。

あまりにも長々とした、または身勝手な説明ではなかったことを願っています。

ComboBox を null にするために何かをする必要があると思います。私が最初に試みることは、ComboBox に ID を与えることです。

<?xml version="1.0" encoding="utf-8"?>
<s:VGroup xmlns:fx="http://ns.adobe.com/mxml/2009" 
         xmlns:s="library://ns.adobe.com/flex/spark" 
         xmlns:mx="library://ns.adobe.com/flex/mx"
         >
    <s:ComboBox id="myComboBox" />
</s:VGroup>

次に、ActionScript コードで、ComboBoxView (関数ローカルではない) のインスタンスを作成します。

protected var vew:ComboBoxView = new ComboBoxView();

そして、次のようにガベージ コレクションを処理します。

        if (hasElement)
        {
            button.setFocus();
            comboBoxContainer.removeAllElements();
            comboBoxContainer.myComboBox = null;
            comboBoxContainer = null;
            hasElement = false;
        } else {
            var vew:ComboBoxView = new ComboBoxView();
            comboBoxContainer.addElement(vew);
            hasElement = true;
        }
    }

私は自分自身でテストを行っていません。私の直感では、これらすべての手順が必要なわけではありません。しかし、私のアプローチはおそらく正しいと思います。

于 2011-02-12T03:31:25.507 に答える