Air Sqlite: Sqlevent.result Not Firing, But Statement Is Executing Properly
Solution 1:
I think what you're missing here is garbage collection.
Haven't tested your code, but this could certainly be the source of the problem.
var sqlReq:SQLRequest = new SQLRequest(handleResult, _dbConn, sql);
sqlReq.startLoad();
The reference sqlReq is local to the function and becomes unreacheable when the function returns. That makes it collectable. I guess there must be some code in the AIR runtime that collects garbage more agressively when there are sql connections involved. Because generally, you'll get away with not storing a ref to your object (at least in a web based environment, in my experience; this is a bug in such code, nevertheless; you just have to be in a bad day to experience it).
The setTimeout masks this problem (or almost solves it, although in an unintended way), because the setTimeout function uses a Timer internally. Running timers are not collected. So, the timer is alive and kicking and has a reference to your SQLRequest instance, which makes it reacheable, and so, not elligible for collection. If your DB call takes longer than the timeout though, you're back in the same situation.
To solve this, store a ref to the object and dispose it properly when you're done.
Edit
Another option, if you don't want to change the way you calling code works, is storing a ref to the instance in a class-scoped (i.e. static) dictionary for the duration of the call (this dictionary shoul not use weak referenced keys for obvious reasons).
You are adding a hidden side effect to your method, which is not a sign of good design in general, but as long as you remove it when the call to the DB is finished (whether it succeded or not), you're safe, so I think the problem is more of style than anything else.
What I mean is something like this:
privatestaticvar _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();
}//executeprivate 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);
}//handleResultprivate function handleError(e:SQLErrorEvent):void
{//handleError// same comment as handleResult
removeFromDict();
trace("SQL Error: " + e.errorID + ": " + e.error);
//dispatchEvent(e);
}//handleErrorprivate function addToDict():void {
_dict[this] = true;
}
private function removeFromDict():void {
if(_dict[this]) {
delete _dict[this];
}
}
Post a Comment for "Air Sqlite: Sqlevent.result Not Firing, But Statement Is Executing Properly"