0

2 つのコンテンツ領域を並べて表示するタブレット アプリを想像してみてください。ディスプレイ全体に表示されるので、高さ 100%、幅 50% になります。リストを 1 つのコンテナーに追加するとします。当然、このリストはディスプレイ全体の半分のスペースを消費します。

さて、私の問題ですが、このサイズのリストでは高フレームレートのスクロールが不可能になる可能性はありますか? 私は最も基本的な AS3 ItemRenderer を持っていますが、スクロール中に 30fps を超えるものはまだ得られません。ここで奇妙なことに、他のコンテナーに何かを追加すると、別のリストや他のコンポーネントを言うと、リストのスクロール パフォーマンスが 20 代前半に低下します。そのため、MAX ショーでアドビの広告が表示される 40+ fps にはほど遠いです。

私は iPad2 と 3 でテストしていますが、静的な値を使用しても、スクロールはあまり良くありません。ItemRenderer のset dataメソッドが呼び出されるようにストリーミング値を有効にすると、フレームレートがさらに 2 ~ 3 フレーム低下します。

私の(ほぼ)完全なレンダラーは次のようになりますが、単一のテキストフィールドを表示するだけにそれを取り除いても、で行われているものを無効にしset data、単一のテキストフィールドのサイズのみを設定してもlayoutContents、パフォーマンスは説明どおりで、約30ですリストが単独で表示されている場合は、他のものも表示されている場合は 20 秒未満です。

    //FCStyleableTextField is just a StyleableTextField with an additional ID

    private var _textFields:Vector.<FCStyleableTextField>;
    private var _oldValues:Dictionary;
    private var _sym:Symbol;

    public function GridRenderer() {
        super();
        _textFields = new Vector.<FCStyleableTextField>();
        _oldValues = new Dictionary();
    }

    override protected function createChildren():void {

        var _symLabel:FCStyleableTextField = new FCStyleableTextField();
        _symLabel.editable = false;
        _symLabel.selectable = false;
        _symLabel.multiline = false;
        _symLabel.id="sym";
        _symLabel.setStyle("fontSize", fontSize);
        _symLabel.textColor = 0xc0c0c0;
        _textFields.push(_symLabel);
        addChild(_symLabel);

        var fidLen:int = fids.length;
        for (var i:int = 0; i<fidLen; i++) {
            var _fid_lbl:FCStyleableTextField = new FCStyleableTextField();
            _fid_lbl.selectable = false;
            _fid_lbl.editable = false;
            _fid_lbl.multiline = false;
            _fid_lbl.id = String(fids[i]);
            _fid_lbl.textColor = 0xc0c0c0;
            _fid_lbl.setStyle("textAlign", "right");
            _fid_lbl.setStyle("fontSize", fontSize);
            _fid_lbl.text = " ";
            _textFields.push(_fid_lbl);
            addChild(_fid_lbl);

            if(i>visibleColumns) {
                _fid_lbl.includeInLayout = false;
                _fid_lbl.visible = false;
            }
        }
    }


    override public function set data(value:Object):void {
        if(!value) return;

        if(data) {
            // check if the value's symbolName is different than the current
            // data's symbolName, if so, the itemRenderer has been 
            // recycled, thus we need to reset the old fid values
            if((value as Symbol).symbolName != (data as Symbol).symbolName)
                _oldValues = new Dictionary();
        }

        super.data = value;

        _sym = data as Symbol;

        try {
            var textLen:int = _textFields.length;
            for (var i:int = 0; i<textLen;i++) {
                var lbl:FCStyleableTextField = _textFields[i];
                if(lbl.id == "sym") {
                    lbl.text = _sym.symbolName;
                    lbl.truncateToFit();
                } else {
                    if(lbl.id == _sym.fidList.fidMap[lbl.id].fidId && lbl.text != _sym.fidList.fidMap[lbl.id].fieldValue) {
                        var time:int = new Date().time;
                        var timerName:String = _sym.symbolName+","+lbl.id+","+grid;
                        globalTimer.addTimer(timerName, time, "reset", lbl, null, null);

                        var _oldVal:* = _oldValues[lbl.id];
                        var _newVal:* = _sym.fidList.fidMap[lbl.id].fieldValue;

                        // basic color formatting
                        if(Number(_newVal) > Number(_oldVal))
                            lbl.textColor = 0x40c040;
                        else if(Number(_newVal) < Number(_oldVal))
                            lbl.textColor = 0xf05050;

                        // add + to change and changePercent fids if value is positive
                        if(lbl.id == "56") {
                            if(_newVal >0)
                                lbl.text = "+" + _newVal;
                            else
                                lbl.text = String(_newVal);
                        } else if(lbl.id == "11") {
                            if(_newVal >0)
                                lbl.text = "+" + _newVal;
                            else 
                                lbl.text = String(_newVal);
                        } else 
                            lbl.text = String(_newVal);

                        if(!_sym.fidList.fidMap[lbl.id].fieldValue)
                            lbl.text =" ";

                        _oldValues[lbl.id] = _newVal;
                    } 
                }

                lbl.truncateToFit();
            }       
        } catch (e:Error) { /* nothing to do here -> try/catch required due to async symbolassembly */ }
    } 

    override protected function layoutContents(unscaledWidth:Number, unscaledHeight:Number):void {
        var viewWidth:Number  = unscaledWidth  - paddingLeft - paddingRight;
        var viewHeight:Number = unscaledHeight - paddingTop  - paddingBottom;
        var _previousLabel:FCStyleableTextField;
        var textLen:int = _textFields.length;

        for(var i:int =0; i<textLen;i++) {
            var lbl:FCStyleableTextField = _textFields[i];
            graphics.beginFill(0x808080, .3);
            lbl.height = viewHeight;
            lbl.y = paddingTop;

            if(lbl.id=="sym") {
                lbl.width = 95;
            } else if (lbl.id == "35000") {
                lbl.width = 24;
            } else { 
                lbl.width = optimalColWidth;
            }

            _previousLabel ? lbl.x = (_previousLabel.x + _previousLabel.width): lbl.x = paddingLeft;
            graphics.drawRect(lbl.x+lbl.width, 1, 1, unscaledHeight-1);

            lbl.commitStyles();
            _previousLabel = lbl;
            graphics.endFill();
        }
    }

それでも、速度低下の原因はアイテム レンダラーではないことは確かです。先ほど述べたように、テキスト フィールドを 1 つだけ表示するレンダラーと比較して、2 フレーム、おそらく 3 フレームのコストがかかるからです。むしろ、一度に表示されるベクトルの量を Flex がどうにか処理できないと思いますが、そのようなことは可能ですか? また、パフォーマンスを向上させる方法はありますか? ユーザーがリストをスクロールするとすぐにライブ ストリーミングの値を無効にしたので、Flex は基本的にビットマップをスクロールするだけで済みます (LabelItemRenderer が自動的に有効になるためcacheasbitmap) が、おそらく 4 フレーム増加しました。スクロールを少しスムーズにするコツは何ですか?

4

1 に答える 1

1

Figured out that using setElementSize() and setElementPosition() instead of using width/height and x/y makes quite a difference. Gained 3fps in initial scrolling performance and 8fps once every item has been rendered. So I'm pretty close to 30fps now, still not close to what you can do with a native app, but I figure that's as good as it gets with Flex and such a massive renderer.

Also disabled live updates so that the renderer doesn't need to be cached as a bitmap again when updates come in.

于 2012-07-31T13:00:08.960 に答える