0

想象一个并排显示两个内容区域的平板电脑应用程序。它们完全填满显示屏,高度为 100%,宽度为 50%。假设我们将一个列表添加到一个容器中。自然这个列表会占用整个显示空间的一半。

现在我的问题是,这种大小的列表是否可能无法实现高帧率滚动?我拥有最基本的 AS3 ItemRenderer,但在滚动期间仍然无法获得高于 30fps 的任何内容。现在奇怪的是,如果我在另一个容器中添加东西,比如说另一个列表或其他组件,列表滚动性能下降到 20 秒。因此,您在 MAX 节目中看到的 Adob​​e 广告远不及 40+ fps。

我正在 iPad2 和 3 上进行测试,即使使用静态值,滚动也不是很好。现在,如果我启用流式传输值以便set data调用 ItemRenderer 的方法,则帧速率会再下降 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();
        }
    }

不过,我很确定不是项目渲染器导致了减速,因为正如我所说,与只显示单个文本字段的渲染器相比,它花费 2 帧,也许 3 帧。我宁愿认为 Flex 无法处理一次显示的矢量数量,这可能吗?有什么方法可以提高性能吗?一旦用户滚动列表,我已经禁用了实时流媒体值,因此 flex 基本上只需要滚动位图(因为 LabelItemRenderer 自动启用cacheasbitmap),但这可能会获得 4 帧。你们有什么技巧可以使滚动更顺畅?

4

1 回答 1

1

发现使用setElementSize()setElementPosition()而不是使用宽度/高度和 x/y 会产生很大的不同。初始滚动性能提高 3fps,渲染每个项目后提高 8fps。所以我现在非常接近 30fps,仍然不能接近原生应用程序所能做到的,但我认为这与使用 Flex 和如此庞大的渲染器一样好。

还禁用了实时更新,以便渲染器在更新时不需要再次缓存为位图。

于 2012-07-31T13:00:08.960 回答