iPad上的Adobe AIR滚动性能(2) - 我能期待什么?

时间:2012-04-17 00:11:07

标签: performance actionscript-3 flex ipad air

我目前正在开发一款针对iPad2作为硬件平台的Adobe AIR应用程序,并且无法在其中一个屏幕上获得不错的滚动性能。我正在使用一个火花清单,其中包含一个自定义项目渲染器:

<s:List id="productList" top="116" bottom="0" left="10" right="10" 
    width="100%"
    visible="true" includeInLayout="true"
    height="0"
    maxHeight="500"
    opaqueBackground="#ffffff"
    itemRenderer="myRenderer">
</s:List>

最初,我使用的是.mxml渲染器,但在看到令人讨厌的性能后,我决定自己滚动,扩展UIComponent(我已经离开了包并支撑以节省水平空间):

import mx.controls.listClasses.IListItemRenderer;
import mx.core.UIComponent;
import mx.events.FlexEvent;
import mx.utils.ColorUtil;

import spark.components.Label;
import spark.components.TextInput;

public final class OrderViewProductLineTestIR extends UIComponent implements IListItemRenderer 
{
    public function OrderViewProductLineTestIR()
    {
        super();
    }

    // Internal variable for the property value.
    private var _data:Object;

    private var productName:Label;
    private var orderQty:TextInput;
    private var stockQty:TextInput;


    // Make the data property bindable.
    [Bindable("dataChange")]

    // Define the getter method.
    public function get data():Object
    {
        return _data;
    }

    // Define the setter method, and dispatch an event when the property
    // changes to support data binding.
    public function set data(value:Object):void
    {
        _data = value;
        invalidateProperties();
        dispatchEvent(new FlexEvent(FlexEvent.DATA_CHANGE));
    }

    override protected function createChildren():void
    {
        super.createChildren();

        productName = new Label();
        // productName.visible = true;
        addChild(productName);

        orderQty = new TextInput();
        addChild(orderQty);

        stockQty = new TextInput();
        addChild(stockQty);

    }

    override protected function commitProperties():void
    {
        super.commitProperties();
        productName.text = _data.Name;
    }

    override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void
    {
        super.updateDisplayList(unscaledWidth, unscaledHeight);
        productName.move(0, 0);
        productName.setActualSize(250, 48);

        orderQty.move(270, 0);
        orderQty.setActualSize(100, 48);

        stockQty.move(390, 0);
        stockQty.setActualSize(100, 48);
    }

    override protected function measure():void
    {
        super.measure();

        measuredWidth = 490;
        measuredHeight = 48; 
    }
}

正如你所看到的那样,它非常轻巧,但我的数据提供者包含了超过100个项目,其中11个可以在任何时候都在屏幕上。我所阅读的关于提高滚动性能的所有内容都围绕着使用opaqueBackgroundcacheAsBitmap,但不管我在哪里都没有帮助。在列表级别使用cacheAsBitmap没有帮助,因为一旦你滚动了几行需要重新渲染整个事物并在项目渲染器级别使用它,项目渲染器就会重新启动在快速滚动时仍然非常慢 - 大概是因为许多人在非常快速的滚动过程中被立即回收。

我知道iPad应该可以毫不费力地以60 fps的速度在一帧画面中显示信息,但是当我快速滚动时,我看到很难达到10 fps(从视线开始)。所以问题是:我是否遗漏了一些明显的东西,或者由于使用AIR时所涉及的层数(和矢量渲染)而导致这种情况需要预期?对于记录,我尝试更改渲染模式对于应用程序并尝试改变帧速率以消除明显的。

3 个答案:

答案 0 :(得分:0)

这有点猜测,但是itemRenderer可以优化吗?每次重新绘制组件时,是否需要对所有子项进行定位和调整大小?每次commitProperties运行时,您是否需要更新productName.text?

以下是我可能会修改的内容:

import mx.controls.listClasses.IListItemRenderer;
import mx.core.UIComponent;
import mx.events.FlexEvent;
import mx.utils.ColorUtil;

import spark.components.Label;
import spark.components.TextInput;

public final class OrderViewProductLineTestIR extends UIComponent implements IListItemRenderer 
{
    public function OrderViewProductLineTestIR()
    {
        super();
    }

    // Internal variable for the property value.

private var _data:Object;

// Add a dataChanged property 
private var dataChanged :Boolean = false

private var productName:Label;
private var orderQty:TextInput;
private var stockQty:TextInput;


// Make the data property bindable.
[Bindable("dataChange")]

// Define the getter method.
public function get data():Object
{
    return _data;
}

// Define the setter method, and dispatch an event when the property
// changes to support data binding.
public function set data(value:Object):void
{
    _data = value;
    // switch the dataChanged flag 
    dataChanged = true;
    invalidateProperties();
    dispatchEvent(new FlexEvent(FlexEvent.DATA_CHANGE));
}

override protected function createChildren():void
{
    super.createChildren();

    productName = new Label();
    // productName.visible = true;
    addChild(productName);

    orderQty = new TextInput();
    addChild(orderQty);

    stockQty = new TextInput();
    addChild(stockQty);

}

override protected function commitProperties():void
{
    super.commitProperties();
    // Only update the display if the data actually changed 
    If(dataChanged){
      productName.text = _data.Name;
      dataChanged = false;
    }
}


// add variable to tell whether the component's children have been sized and positioned or not
// since they have static locations, no need to set these each time
protected var compChildrenSized :Boolean = false;
override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void
{
    super.updateDisplayList(unscaledWidth, unscaledHeight);
    if(!compChildrenSized){
     productName.move(0, 0);
     productName.setActualSize(250, 48);

     orderQty.move(270, 0);
     orderQty.setActualSize(100, 48);

     stockQty.move(390, 0);
     stockQty.setActualSize(100, 48);

     compChildrenSized = true;
    }
}

override protected function measure():void
{
    super.measure();

    measuredWidth = 490;
    measuredHeight = 48; 
}
}

我想我会补充一点,我不确定措施会不会运行。如果用标签替换textInputs会发生什么?您使用的是Flex 4.6,如果是这样,您使用的是StyleableStageText(AKA StageText)还是使用StyleableTextField的4.5皮肤?我想知道StageText滚动是否会导致性能下降,因为它会挂在Flash显示列表上方。

如果完全删除textInput并用标签替换会怎样?

这些都是小事,我不确定他们是否会提供帮助。

答案 1 :(得分:0)

在“Spark列表组件”上试试这个 1 /添加布局(水平或垂直取决于你想要的;)
2 /在列表组件上添加属性“useVirtualLayout = true”!
并告诉我结果是什么......但我认为它会更顺畅(非常非常平滑), 因为当您将元素添加到列表时,即使是,也会渲染所有组件 它们不在布局中......所以“useVirtualLayout”只是视口上的项目被渲染,其他项目被销毁......

拜拜 !和Flash Builder一起玩得开心!拥有多支持应用程序是一项非常酷的技术!

答案 2 :(得分:-1)

有点晚了。但

如果你想要接近本机性能的话,最好使用椋鸟和羽毛。

但您仍然可以优化渲染器。 请勿在Flex移动应用程序中的任何位置使用绑定。 扩展UIComponent是正确的做法。 我认为不使用失效并在数据设置器中设置属性会更好。

希望它有所帮助。