初始化完成后:
点击左侧目录后:
具体实现:
初始化时:
//Main - Maincontent vboxMainRightcontent = new VBox(); empListContainer = new MainContent(); empListContainer.visible = false; vboxMainRightcontent.addChild(empListContainer); //----------------------------加入button 测试 invilidate...---------- testButton.label = "我是来测试的"; vboxMainRightcontent.addChild(testButton); empListContainer.explicitHeight = 0;//注意此处, 设置为0方可不占用界面中的场地, 注意在visable设置为true之后还要进行相应的调整 empListContainer.explicitWidth = 0;
左侧目录被点击后:
//---------------------------------Listeners------------------------ //Listener - onListChange private function onDepListChange(e:ListEvent):void { _empListContainer.visible = _treeDepCat.selectedItem != null; if(_empListContainer.visible) { _empListContainer.explicitHeight = undefined;//将explicitHeight复原, 否则虽然已经visable, 但其宽高都是0 仍无法可见. _empListContainer.explicitWidth = undefined; }else { _empListContainer.explicitHeight = 0; _empListContainer.explicitWidth = 0; }
要求: 如下编辑器:
编辑职员信息, 在验证其输入均合法之后, 并判断该对象是否需要保存 – 如果没有改变, 则不需要保存
分析:
1. 可继承Vbox等组件设计该Edtior
主要进行创建, 添加组件等操作…
2. 设定编辑对象, 设定正在编辑的职员, 并将相关信息输出到Editor中.
/** * 给定正在编辑的职员 */ public function set editorData(editorData_:Employee):void { _editorData = editorData_; textID.text = editorData_.id.toString(); textName.text = editorData_.name; textAge.text = editorData_.age.toString(); textAddress.text = editorData_.address; if(editorData_.isMale > 0) { if(editorData_.isMale != 1) { _radioNotMals.selected = true; }else { _radioIsMale.selected = true; } }else {//新建情况下 两个readiobutton均不选择 - 通过validation提示用户选择 _radioIsMale.selected = false; _radioNotMals.selected = false; } if(editorData_.level > -1 ) { comboLevel.selectedIndex = editorData_.level; }else {//新建时 comboLevel.selectedIndex = 0; } validateAll(); }
3. 验证输入数据, 是否合法
见: http://liguoliang.com/2009/02/780/
4. 判断对象是否有改动, 若有改动则enable Save Button. 否则继续unable.
//---------------------------设置Save Button的可用性, 输入合法, 并且至少有一项是dirtyt的才能enable------------------------------ private function setButton():void { if(_editorData == null) { return; } var allValidate:Boolean = (textName.errorString == null && textAge.errorString == null && hboxIsMale.errorString == null && comboLevel.errorString == null); var anyOneDirty:Boolean = (_editorData.name != inputName || _editorData.age != inputAge || _editorData.isMale != inputIsMale() || _editorData.level != inputLevel() || _editorData.address != inputAddress()); if(allValidate && anyOneDirty) { buttonSave.enabled = true; return; } buttonSave.enabled = false; }
输入通过验证, 并检测到数据发生变化时, Enable Save Button:
按照MVC, Save及Cancel等操作应交由Control进行操作.
如: 某编辑器:
代码:
textName.addEventListener(Event.CHANGE, onTextNameChange);//增加监听函数,监听EventChange, 如果不需实时验证, 可监听FlexEvent.VALUE_COMMIT事件. //------------------Validation - Name - on Event.Change------------ private function onTextNameChange(e:Event = null):void { if(StringUtils.trim(textName.text).length < 2) { textName.errorString = "Name不能少于2个字符, 请重新输入"; }else if(StringUtils.trim(textName.text) == "String") { textName.errorString = "Name不可为'String'"; }else { textName.errorString = null; } setButton(); }
1. get Operation
2. set arguments
3. AddResponder, Send();
如下:
private var op:AbstractOperation; public function loadEmployees():void { op = AppContext.getRemoteObject().getOperation("loadEmployees"); //获得Operation op.arguments = [id]; //设定参数 op.send(); var at:AsyncToken = op.send(); //Send at.addResponder(this); //为本实例增加responder } //使用当前类响应, 则应实现IResponder接口, 要实现两个方法, 如下: //---------------------Responder------------------------------- public function result(responderResult:Object):void { var resultEvent:ResultEvent = responderResult as ResultEvent;//转换 var ac:ArrayCollection = resultEvent.result as ArrayCollection;//获得Result log.debug("已读取到 " + this + "的职员列表, 职员数目为: " + ac.length); } public function fault(data:Object):void { throw new Error("远程操作失败"); }
原先的错误方法:
private var op:AbstractOperation; public function loadEmployees():void { op = AppContext.getRemoteObject().getOperation("loadEmployees"); //获得Operation op.arguments = [id]; //设定参数 op.addEventListener(ResultEvent.RESULT, onSqlResult,false, 0, true); op.send(); // var at:AsyncToken = op.send(); //Send //at.addResponder(this); //为本实例增加responder } private function onSqlResult(e:ResultEvent):void { var ac:ArrayCollection = e.result as ArrayCollection; for each(var emp:Employee in ac) { emp.department = this; employeeAC.addItem(emp); } log.debug("已读取到 " + this + "的职员列表, 职员数目为: " + ac.length); op.removeEventListener(ResultEvent.RESULT, onSqlResult);//更错误的方法是没有remove Listener }
这样导致该方法被呼叫时, op都会被监听, 成功后取消监听, 如果不取消监听, 则会出现如下输出信息:
第一次调用:
[DEBUG] Department 已读取到 Dep1的职员列表, 职员数目为: 2
第二次调用:
[DEBUG] Department 已读取到 Dep1的职员列表, 职员数目为: 2
[DEBUG] Department 已读取到 Dep2的职员列表, 职员数目为: 2
第三次调用:
[DEBUG] Department 已读取到 Dep1的职员列表, 职员数目为: 0
[DEBUG] Department 已读取到 Dep2的职员列表, 职员数目为: 0
[DEBUG] Department 已读取到 Department3的职员列表, 职员数目为: 0
在此情况下, op可视为一类操作, 这样在使用op[他会有很多个实例, 会有很多个对应的监听函数]监听之后, 每个实例的Result的返回都会引发所有实例的Listener运行. 因此会出现上面的状况.
1. Flex中的Trace, Java/Flex中的log, 并不能代表其真实行为.
2. 务必牢记重写toString方法
3. Flex: 在跨越幅度较大, 设计Obj较多时, 使用weakreference的 Event Listener
4. 关于weakreference, 相对普通reference来说, weakreference像一个棉线, 牵着Obj – 但不妨碍garage Collection, 而普通reference则像铁链一样牢牢绑着obj, 会阻止进行garage Collection. 如果一个Object只有weak reference指向他, 则基本可以视为已经被garage Collection,
5. 可以在每个Class中加入一个Object_ID Filed, 在构造函数中使用randomNumber填充 – 便于分辨对象
6. JDBC 的 traction不是线程安全的
7. 谨慎使用ArrayCollection, Array的sort, filter功能 – 因为这会打乱其自身. 在使用其作为DataProvider时, 应使用ListCollectionView, 这样在进行操作时则其本身不会有任何改变
// Proudly powered by Apache, PHP, MySQL, WordPress, Bootstrap, etc,.