AIR Sqlite:SQLEvent.RESULT未触发,但语句IS正确执行
好吧看起来好像我偶然发现了一个奇怪的计时问题……我为执行sql语句做了一个快速的SQL包装器类.但是,在调用.execute()之后,永远不会触发SQLEvent.RESULT事件,但DB中的新条目将按原样创建.真正奇怪的部分是如果我在调用execute()之后放置一个setTimeout(),事件会按预期触发..我希望我在这里找不到一些非常明显的东西……这是一个示例air app的链接:
http://www.massivepoint.com/airsqltest/AIRSQL.zip 以下是包装类的代码: 如果你向下看SQLRequest类中的第51行,你会看到注释掉的setTimeout()方法.为了让一切顺利,只要取消注释那条线……但对我来说这没有任何意义…… 有人有什么想法?我完全被这里难过…… package com.jac.sqlite {//Package import flash.data.SQLConnection; import flash.data.SQLStatement; import flash.events.EventDispatcher; import flash.events.SQLErrorEvent; import flash.events.SQLEvent; import flash.utils.setTimeout; public class SQLRequest extends EventDispatcher {//SQLRequest Class private var _callback:Function; private var _dbConn:SQLConnection; private var _query:String; private var _params:Object; private var _statement:SQLStatement; public function SQLRequest(callback:Function,connection:SQLConnection,query:String,parameters:Object=null):void {//SQLRequest trace("Creating new SQL Request"); _callback = callback; _dbConn = connection; _query = query; _params = parameters; _statement = new SQLStatement(); _statement.sqlConnection = _dbConn; _statement.text = _query; if (_params != null) {//assign for (var param:String in _params) {//params trace("Setting Param: " + param + " to: " + _params[param]); _statement.parameters[param] = _params[param]; }//params }//assign //setup events _statement.addEventListener(SQLEvent.RESULT,handleResult,false,true); _statement.addEventListener(SQLErrorEvent.ERROR,handleError,true); }//SQLRequest public function startLoad():void {//execute _statement.execute(); //setTimeout(handleTimeOut,10000); }//execute //TEMP private function handleTimeOut():void {//handleTimeOut trace("Executing: " + _statement.executing + " / " + executing); }//handleTimeOut private function handleResult(e:SQLEvent):void {//handleResult trace("Good SQL Request"); _callback(e); dispatchEvent(e); }//handleResult private function handleError(e:SQLErrorEvent):void {//handleError trace("SQL Error: " + e.errorID + ": " + e.error); //dispatchEvent(e); }//handleError public function get executing():Boolean {//get executing return _statement.executing; }//get executing public function get query():String { return _query; } public function get statement():SQLStatement { return _statement; } }//SQLRequest Class }//Package 解决方法我想你在这里缺少的是垃圾收集.没有测试过您的代码,但这肯定是问题的根源. var sqlReq:SQLRequest = new SQLRequest(handleResult,_dbConn,sql); sqlReq.startLoad(); 引用sqlReq是函数的本地函数,并在函数返回时变为不可缓存.这使它可收藏.我想在AIR运行时必须有一些代码,当涉及到SQL连接时,它会更加积极地收集垃圾.因为通常情况下,你不会将ref存储到你的对象中(至少在基于web的环境中,根据我的经验;这是这类代码中的一个错误;然而你只需要在糟糕的一天中体验它). setTimeout掩盖了这个问题(或者几乎解决了它,尽管是以一种无意的方式),因为setTimeout函数在内部使用了Timer.不收集运行计时器.因此,计时器处于活动状态并且具有对SQLRequest实例的引用,这使得它可以进行访问,因此不适合收集.如果您的数据库调用花费的时间超过了超时,那么您将恢复相同的状态. 要解决此问题,请将ref存储到对象并在完成后正确处理. 编辑 另一个选项,如果你不想改变调用代码的方式,则在调用期间将一个ref存储在类范围(即静态)字典中(该字典不应使用弱引用键原因很明显). 您正在为方法添加隐藏的副作用,这通常不是良好设计的标志,但只要在完成对DB的调用(无论是否成功)时将其删除,您就是安全的,所以我认为问题更多的是风格而不是其他任何东西. 我的意思是这样的: private static var _dict:Dictionary = new Dictionary(); public function startLoad():void {//execute _statement.execute(); // add a self reference to dict so the instance won't be collected // do this in the last line,so if we have an exception in execute,this // code will not run (or add a try/catch if you want,but this is simpler // and cleaner,IMO addToDict(); }//execute private function handleResult(e:SQLEvent):void {//handleResult // remove the self reference before running any other code // (again,this is in case the code that follows throws) removeFromDict(); trace("Good SQL Request"); _callback(e); dispatchEvent(e); }//handleResult private function handleError(e:SQLErrorEvent):void {//handleError // same comment as handleResult removeFromDict(); trace("SQL Error: " + e.errorID + ": " + e.error); //dispatchEvent(e); }//handleError private function addToDict():void { _dict[this] = true; } private function removeFromDict():void { if(_dict[this]) { delete _dict[this]; } } (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |