FLEX ERROR WARNING 小结

FLEX ERROR WARNING 总结
常会碰到的错误:TypeError: Error #1009: 无法访问空对象引用的属性或方法。

http://hillelcoren.com/2008/09/19/flex-error-1009-cannot-access-a-property-or-method-of-a-null-object-reference/
Flex 2 Runtime Error 1009 and Runtime Modules:
http://life.neophi.com/danielr/2006/07/flex_2_runtime_error_1009_and.html
我碰到的Error #1009:
在一个弹出页面的TitleWindow的写了initialize="initComboBox();"
/**
			 * remark routeN等 都为本titleWindow页的ComboBox组件
			 * */
			private function initComboBox():void {
				///fidsDepfVo不会为null
				remark.selectedIndex = 1;
				route1.selectedIndex = 1;
				route2.selectedIndex = 2;
				route3.selectedIndex = 3;
				route4.selectedIndex = 4;
				route5.selectedIndex = 5;
				route6.selectedIndex = 6;
			}
结果在route1那行代码报了“无法访问空对象引用的属性或方法”;经debug,发现route1及其后的route2-6居然都为null(remark不为null,为ComboBox实例)!(说明下:页面中ComboBOx remark 是定义在 route1-6 六个 ComboBox之前的)。后来将 initialize="initComboBox();" 改为  creationComplete="initComboBox();" ,不再报错。
本次问题表明:了解mxml文件的初始化顺序是至关重要的!不要在initialize中访问本页面的组件,因为这样可能会出现不可预知的错误!
关于Flex Application 初始化顺序:
http://wuaner.iteye.com/blog/1054116





values of type spark.layouts.supportClasses.LayoutBase cannot be represented in text
http://flexspaghetti.wordpress.com/2009/06/13/setting-the-layout-property-in-flex-4/









问题代码:
引用
<s:ComboBox width="124" id="term1" change="select_changeHandler(event, this.term1);"
								dataProvider="{this.parentApplication.terminalDataList}" labelFunction="terminalCombineDisplay" />
private function terminalCombineDisplay(item:Object):String {
				if(null!=item) {
					return StringUtil.substitute("{0}-{1}", item.@code, item.@cname);
				} else {
					return null;
				}
			}
出错:
引用
ReferenceError: Error #1081: 在 Object 上找不到属性 code,且没有默认值。
原因:
引用
Object item 是通过调用remoteObject从后台得的ArrayCollection;而 obj.@atr这种取属性的方式是mx:XMLList才可以用的(貌似是?有待着日再议;反正用在ArrayCollection上确实不行)。
解决办法:取属性时去掉@:
引用
private function terminalCombineDisplay(item:Object):String {
				if(null!=item) {
					return StringUtil.substitute("{0}-{1}", item.code, item.cname);
				} else {
					return null;
				}
			}
总结:之所以犯这个错误,是因为参照了下面的帖子(该帖Combox里放的是mx:XMLList,Combox的labelFunction中使用 obj.@atr 的方式取Combox的item的属性)。总之一句话吧,Copy别人代码,出错在所难免;但倒也能长点知识:
Creating a simple label function on a Flex ComboBox control:
http://blog.flexexamples.com/2007/09/25/creating-a-simple-label-function-on-a-flex-combobox-control/






在<mx:itemRenderer>中使用内联的<fx:Script>时,得到如下Warning:
%s will be scoped to the default namespace: %s internal. It will not be visible outside of this package.

官方解释:
http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/compilerWarnings.html
引用
Not declaring a namespace is a coding style preference. Enable this warning if you want to be reminded when you forget to declare a namespace or access specifier for a definition. Without one, the definition is not visible to code located outside of this file. To make it visible to code outside this file, declare it with the access specifier public or with a namespace declaration. To keep the definition local to this file and avoid this warning, declare the definition as private. 
So,出该warning的原因就是未为内联script里的var变量定义加访问修饰符的原因,解决办法就是加*问修饰符:
http://*.com/questions/245155/default-namespace-scope-warning-1084-in-flex-script-file
引用
Stick a private, protected, internal or public before the function declaration:
private function btnBadLogin_onClick():void
这里引出flex的访问修饰符及其可见性:
http://www.flexer.info/2008/01/07/publicprotectedprivateinternalstatic/
引用
FLEX ERROR WARNING 小结






Warning:
Data binding will not be able to detect assignments to 'cht1'
出现Warning的代码:
<fx:Binding source="cht1.selectedItem.data" destination="fidsDepfVo.chuter.cht1" twoWay="true"/>

原因:vo chuter未声明为绑定对象。未声明为Bindable。
解决办法:将FidsDepfChuterVo声明为[Bindable]即可:
package com.bcia.fids.ops.depf.entity
{
	[Bindable]  
	[RemoteClass(alias="com.bcia.fids.application.comm.entity.FidsDepfChuter")]
	public class FidsDepfChuterVo
	{
		public function FidsDepfChuterVo()
		{
		}
		
		public var id:String;







一个警告:
warning: unable to bind to property 'data' on class 'Object' (class is not an IEventDispatcher)
警告代码:
<fx:Binding source="domint.selectedItem.data" destination="fidsDepfVo.domint" twoWay="true"/>
警告原因:domint是个ComboBox,其dataProvider是放有Object的ArrayCollection。因为Object不是EventDispatcher,所以当Object的属性change的时候,就无法dispatch "propertyChange"这个事件
Flex Error : class is not an IEventDispatcher:
http://blog.flexuous.com/2006/10/25/flex-error-class-is-not-an-ieventdispatcher/
Flex Warning: Unable to bind to property ‘XXX’ on class ‘XXX’:
http://www.thedesilva.com/2009/02/flex-warning-unable-to-bind-to-property-%E2%80%98xxx%E2%80%99-on-class-%E2%80%98xxx%E2%80%99/
对于一个单个的对象Object,想解决这个问题,使用代理对象 ObjectProxy 来代理原对象是比较好的解决办法:
import mx.events.PropertyChangeEvent;
      import mx.utils.ObjectUtil;
      import mx.utils.ObjectProxy;
      import mx.utils.StringUtil;
           var a:Object = { name: "Tyler", age: 5, ssnum: "555-55-5555" };
      var p:ObjectProxy = new ObjectProxy(a);
      p.addEventListener(PropertyChangeEvent.PROPERTY_CHANGE, updateHandler);
      p.name = "Jacey";
      p.age = 2;
      delete p.ssnum;
           // handler function
      function updateHandler(event:PropertyChangeEvent):void
      {
          trace(StringUtil.substitute("updateHandler('{0}', {1}, {2}, {3}, '{4}')",
                                         event.kind,
                                         event.property,
                                         event.oldValue,
                                         event.newValue,
                                         event.target.uid));
      }
           // trace output
      updateHandler('opUpdate', name, Jacey, '698AF8CB-B3D9-21A3-1AFFDGHT89075CD2')
      updateHandler('opUpdate', age, 2, '698AF8CB-B3D9-21A3-1AFFDGHT89075CD2')
      updateHandler('opDelete', ssnum, null, '698AF8CB-B3D9-21A3-1AFFDGHT89075CD2')
[b][size=small]但我现在遇到的问题是:通过remoteObject调用java后台(后台java方法的返回类型为List<ComboBoxEntity>)返回的ArrayCollection中的对象为Object类型。那怎么办那?还是用ObjectProxy,通过遍历远程返回的list逐个代理里头的对象是未尝不可的:
private function onResult(r:ResultEvent) : void {
    var quotes: ArrayCollection = r.result.quotes;
    var wrappedQuotes = new ArrayCollection();
    for each (var quote in quotes)
    wrappedQuotes.addItem(new ObjectProxy(quote))
    view. dataProvider = wrappedQuotes;
}
但如果数据量比较客观,则这个遍历的操作就显得很是不该的。于是想用其他的办法来做。首先想到的是在本地建立一个VO:[/size][/b]
package com.bcia.fids.ops.depf.entity
{
	[Bindable]
	[RemoteClass(alias="com.bcia.fids.application.maintenance.ops.depf.dto.ComboBoxEntity")]
	public class ComboBoxVo
	{
		public function ComboBoxVo()
		{
		}
		public var id:String;  //数据库主键
		public var label:String;  ///显示label(中文名称等)
		public var data:String;  //业务主键code等
	}
}
但经测试后发现,java后台返回的ArrayCollection中存放的仍然是Object!后来通过在mxml文件中通过registerClassAlias注册ComboBoxVo,解决了这个问题,ArrayCollection中存放的对象不再是Object,而变成了需要的ComboBoxVo:
<fx:Script>
		<![CDATA[
			flash.net.registerClassAlias("lasjdlkfajskdfj",ComboBoxVo);
			
			import com.bcia.fids.ops.depf.entity.ComboBoxVo;
...
至此,这个从java后台传回的ArrayCollection中存放的不再是Object,而是我们已经声明为[Bindable]的ComboBoxVo;从而在使用它作为ComboBox的DataProvider,并将这个ComboBox与fidsDepfVo的某属性做双向绑定的时候,不再报这个警告。
从而得出结论:
前台value object和后台pojo的相互转换,必须是相互的。
建立VO对象,并指定其RemoteClass,仅能使前台Vo(这里的ComboBoxVo)在传给java后台后能被识别为java pojo(这里的ComboBoxEntity),即作用于前台FLEX Vo转后台Java POJO的时候。
而对于后台Java POJO转前台Flex Vo,必须在mxml文件中注册Flex Vo
flash.net.registerClassAlias("JAVA端的类全名",AS类名);








Why does adding Bindable to a Getter and Setter Method cause a compiler warning?
http://www.jeffryhouser.com/index.cfm/2008/12/16/Why-does-adding-Bindable-to-a-Getter-and-Setter-Method-cause-a-compiler-warning