Performance Adobe AIR Scrolling在iPad上的性能(2)-我能期待什么?
我目前正在开发一个AdobeAIR应用程序,该应用程序以iPad2为硬件平台,无法在其中一个屏幕上获得良好的滚动性能。我使用的是一个spark列表,带有如下自定义项目渲染器:Performance Adobe AIR Scrolling在iPad上的性能(2)-我能期待什么?,performance,actionscript-3,apache-flex,ipad,air,Performance,Actionscript 3,Apache Flex,Ipad,Air,我目前正在开发一个AdobeAIR应用程序,该应用程序以iPad2为硬件平台,无法在其中一个屏幕上获得良好的滚动性能。我使用的是一个spark列表,带有如下自定义项目渲染器: <s:List id="productList" top="116" bottom="0" left="10" right="10" width="100%" visible="true" includeInLayout="true" height="0" maxHeight="50
<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>
正如您所看到的,这是相当轻的重量,但我的数据提供程序包含100个以上的项目,其中11个项目可以在任何时候出现在屏幕上。我所读到的关于提高滚动性能的所有内容都是围绕使用opaqueBackground
和cacheAsBitmap
展开的,但是无论我尝试了什么,这里都没有帮助。在列表级别使用cacheAsBitmap
没有任何帮助,因为一旦您滚动了超过两行需要重新渲染整个内容时,项目渲染器循环就会启动,当快速滚动时,在项目渲染器级别使用它的速度仍然非常慢——可能是因为在非常快速的滚动过程中,许多项目同时被回收
我知道iPad在一帧中以60 fps的速度快速播放一屏信息应该没有问题,但当我快速滚动时,我发现它很难以10 fps的速度播放(从视线中)。因此,问题是:我是否错过了一些明显的东西,或者这是由于使用AIR时涉及的层数(和矢量渲染)导致的吗?对于记录,我已尝试更改应用程序的渲染模式,并尝试更改帧速率以消除明显的问题 这有点猜测,但是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替换为标签,会发生什么情况?您使用的是Flex4.6吗?如果是,您使用的是StyleableStageText(又名StageText)还是使用StyleableTextField的4.5皮肤?我想知道StageText滚动是否会扼杀性能,因为它挂在Flash显示列表的上方
如果完全删除textInput并替换为标签,会发生什么情况
这些都是小事,我不确定它们是否有用 在你的“火花列表组件”上试试这个1/添加布局(水平或垂直,取决于所需内容;)
2/在列表组件上添加属性“useVirtualLayout=true”
告诉我结果是什么。。。但我认为它会更平滑(非常平滑), 因为当您将元素添加到列表中时,所有组件都会呈现,即使 他们在布局之外。。。因此,使用“useVirtualLayout”只渲染视口中的项目,其他项目则被销毁。。。
再见!享受Flash Builder带来的乐趣!拥有一个多支持应用程序是一项非常酷的技术 有点晚了。但是 的确,如果你想要接近本地性能的东西,最好使用椋鸟和羽毛 但您仍然可以优化渲染器。 请不要在Flex mobile应用程序中的任何位置使用绑定。 扩展UIComponent是正确的做法。 我认为最好不要使用invalidate并在数据设置器中设置属性
希望能有所帮助。有一件事你可能想试试。在您的情况下,看起来不需要从覆盖中调用super。老实说,虽然你不会从Spark列表中获得本地性能。如果您有足够的灵活性,您可能需要签出foxhole GPU组件:。而不是cacheAsBitmap,对于移动设备,您需要cacheAsBitmapMatrix。看见但即便如此。。。我经常提醒人们flash虚拟机非常糟糕。史蒂夫·乔布斯不想在他的设备上安装它是有原因的。我不想在这里挑起粉丝大战,我不是苹果或flash的粉丝,我只是在说实话。Adobe在LLVM.org上发布了一个基准测试,显示AS3的性能大约是原生C的1%,并且随着LLVM优化(偶尔)达到30%的峰值。另外,我很好奇您构建的AIR版本是什么。请参阅下面的帖子,它可能对您有所帮助。我尝试使用标识矩阵缓存AsBitMapMatrix,不幸的是,由于某种原因,它导致图像模糊-看起来渲染到的多边形没有与视图端口1:1映射。我怀疑这只是AdobeBloat杀死它的一个例子:(我使用的是AIR3.2和Flex4。6@shaunhusain你漏掉了一个词:)从我读到的UIComponent是最轻的扩展基础…尝试了上述方法,但没有效果,虽然代码显然更为优化,但我认为瓶颈在堆栈的更底层——很可能就在Adobe下面的代码层中。谢谢你的支持,谢谢。虽然有点问题,但没有什么不同,很确定它已经在回收电池了。真不明白这样一个强大的设备怎么能像这样跪下来!
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;
}
}