对itemrenderer的一些认知(1)-理解data driven
第一阶段的快完成了,回想一下做的过程中遇到问题,分成好几个写下来,希望对大家有帮助
首先是itemrenderer,刚开始的过程对我来说太痛苦了,在还没有充分理解它之前,简直是太二了。其中经典问题之一就是滚动后数据错位和保存的问题,小谈一下:
关键在于itemrenderer是一种data driven的东西,adobe为了提高performance会在可见的范围内建立n+1或2个itemrenderer,这就是为什么会出现拉动滚动条后出现错位的情况,因为滚动后出现的itemrenderer并不是全新的,而是沿用了滚动前已经建好了的,如果你没有重设新建的行的itemrenderer的data属性,新建的itemrender就会分配到的之前已经建好的并延用的itemrenderer的属性,比如背景颜色,选中的项等等。
所以,一定要在itemrenderer里override set data(),并且在这个set方法里用if else判定属性的变化重设各种属性,才能使每一次新建的itemrenderer都是类似于新的。而且如果想对某个itemrenderer做变化并记录,一定要用一个变量去记录,这个变量可以是定义
1. 在这个itemrenderer的容器里,
2. 或更直观的用类似于data.name这种方式去记录,
千万不能是随意一个定义在itemrenderer里的变量,这样下一次重建这行的temrenderer的时候系统就会找到这个已经存在的变量,并且赋给这个itemrenderer。这样你就能用这个变量去改变这个itemrenderer了
这个文章讲的非常好,这个文章讲的非常好,看完之后能知道原理,下面有例子,能帮助理解和自己使用
http://www.adobe.com/devnet/flex/articles/itemrenderers_pt1.html
这是我用到的一个combobox的itemrenderer,里面还有一些别的tricks,之后再详说,现在主要看data那块:
public class ActionComboBoxRenderer extends ComboBox{public function ActionComboBoxRenderer(){super();}override protected function createChildren():void{super.createChildren();}public var actionList:ArrayCollection;public var selectedAction:ActionVo; //这些量是用来跟父容器交互的public var currentOwner:LinkageIPPDataGrid;public var currentOwnerDataProvider:ArrayCollection;public var index:int;override public function set data(value:Object):void {super.data = value; // this must be calledcurrentOwner = new LinkageIPPDataGrid();currentOwner = owner as LinkageIPPDataGrid;this.dataProvider = null; //因为我每点一次这个combobox都问后台要数据做dataProvider,所以要听这两个eventsthis.addEventListener(DropdownEvent.OPEN, this.loadActionList);this.addEventListener(ListEvent.CHANGE , this.handleSelect);//这个就是用来检查属性的改变的方法checkActionSelect();}public function checkActionSelect():void{ //获得父容器的信息currentOwnerDataProvider = currentOwner.dataProvider as ArrayCollection;index = currentOwnerDataProvider.getItemIndex(data);var obj:Object = currentOwnerDataProvider.getItemAt(index);if(obj.selectedAction){data.selectAct = obj.selectedAction;} //这一块是关键,就是这里体现了对属性的改变,一定要用if和else,如果漏了else,就等着错位吧if(data.selectAct){this.prompt = data.selectAct.actionName;if(data.selectAct.actionId == "2"){this.setStyle("chromeColor", 0x00CC00);}else if(data.selectAct.actionId == "3"){this.setStyle("chromeColor", 0xff1d23);}}else{this.prompt = "Select";this.setStyle("chromeColor", "white");} }public function loadActionList(event:DropdownEvent):void{this.removeEventListener(DropdownEvent.OPEN, loadActionList);LinkageHttpService.getInstance().addEventListener(ActionListRendererEvent.ACTION_LIST, handleActionListData);LinkageHttpService.getInstance().getActionList();} //对后台数据的请求和对选择了数据的public function handleActionListData(event:ActionListRendererEvent):void{this.actionList = event.dataCollection;this.dataProvider = actionList;this.labelField = "actionName";this.open();LinkageHttpService.getInstance().removeEventListener(ActionListRendererEvent.ACTION_LIST, handleActionListData);} //对选择了数据的保存,是通过用event传给从父容器并用自身data.selectAct来保存public function handleSelect(event:ListEvent):void{currentOwnerDataProvider = currentOwner.dataProvider as ArrayCollection;index = currentOwnerDataProvider.getItemIndex(data);this.selectedAction = actionList.getItemAt(this.selectedIndex) as ActionVo;if(this.selectedAction is ActionVo){if(this.selectedAction.actionId == "2"){this.setStyle("chromeColor", 0x00CC00);}else this.setStyle("chromeColor", 0xff1d23);}else this.setStyle("chromeColor", 0xffffff);this.data.selectAct = selectedAction;this.dispatchEvent(new ActionSelectEvent("actionSelected", selectedAction, index));}override public function validateNow():void{super.validateNow();this.height = 26;this.y += 8;} }好吧,code单独拿出来可能不容易看懂,但要看的重点应该够清楚,下次再讲讲里面的比如父容器交互的问题吧