////////////////////////////////////////////////////////////////////////////////
//
// RemoteDataLoader
//
////////////////////////////////////////////////////////////////////////////////
package com.eccac.utils
{
import flash.events.Event;
import flash.events.EventDispatcher;
import flash.events.IOErrorEvent;
import flash.events.SecurityErrorEvent;
import flash.net.URLLoader;
import mx.controls.AdvancedDataGridBaseEx;
import mx.rpc.events.FaultEvent;
import mx.rpc.events.ResultEvent;
import mx.rpc.http.HTTPService;
public class RemoteDataLoader
{
//--------------------------------------------------------------------------
//
// Class constants
//
//--------------------------------------------------------------------------
/**
* URLLoader
*/
public static const URLLOADER:int = 0;
/**
* HTTPService
*/
public static const HTTPSERVICE:int = 1;
/**
* WebService
*/
public static const WEBSERVICE:int = 2;
/**
* WebService
*/
public static const LOADING_TEXT:String = "加载中...";
//--------------------------------------------------------------------------
//
// Constructor
//
//--------------------------------------------------------------------------
/**
* Constructor
*/
public function RemoteDataLoader(loaderType:int, requestFunction:Function,
resultFunction:Function)
{
super();
this.loaderType = loaderType;
this.requestFunction = requestFunction;
this.resultFunction = resultFunction;
}
//--------------------------------------------------------------------------
//
// Variables
//
//--------------------------------------------------------------------------
/**
* loader类型
*/
private var loaderType:int = 0;
/**
* 最大loader数
*/
private var maxLoaderCount:int = 1;
/**
* TransformDictionary对象
*/
private var transformDictionary:TransformDictionary =
new TransformDictionary();
/**
* 存放需要向服务器进行请求的元素
* 数组元素为数组: [0]-key; [1]-requested
*/
private var requests:Array = new Array();
/**
* loader对象数组, 用于存放URLLoader/HTTPService/WebService等
* 数组元素为数组: [0]-loader; [1]-key; [2]-busy;
*/
private var loaders:Array = new Array();
//--------------------------------------------------------------------------
//
// Properties
//
//--------------------------------------------------------------------------
//----------------------------------
// requestFunction
//----------------------------------
/**
* 向服务器端发送请求时执行的函数
* function xxx(loader:EventDispatcher, data:Object):void {}
*/
private var _requestFunction:Function = null;
/**
* @private
*/
public function get requestFunction():Function
{
return _requestFunction;
}
/**
* @private
*/
public function set requestFunction(value:Function):void
{
_requestFunction = value;
}
//----------------------------------
// resultFunction
//----------------------------------
/**
* 加载数据成功执行的函数
* function xxx(data:Object):Object {}
*/
private var _resultFunction:Function = null;
/**
* @private
*/
public function get resultFunction():Function
{
return _resultFunction;
}
/**
* @private
*/
public function set resultFunction(value:Function):void
{
_resultFunction = value;
}
//----------------------------------
// grid
//----------------------------------
/**
* 表格对象
*/
private var _grid:AdvancedDataGridBaseEx = null;
/**
* @private
*/
public function get grid():AdvancedDataGridBaseEx
{
return _grid;
}
/**
* @private
*/
public function set grid(value:AdvancedDataGridBaseEx):void
{
_grid = value;
}
//--------------------------------------------------------------------------
//
// Methods
//
//--------------------------------------------------------------------------
/**
* 由指定key获取返回值
*/
public function getResult(key:Object):String
{
var result:String = LOADING_TEXT;
if (transformDictionary.getValue(key) == undefined)
{
loadRequest(key);
return result;
}
return transformDictionary.getDisplayText(key);
}
/**
* 加载请求
*/
private function loadRequest(key:Object):void
{
var loader:EventDispatcher = null;
var keyIndex:int = -1;
var index:int = -1;
keyIndex = getKeyIndex(key);
if (keyIndex >= 0 && requests[keyIndex][1] == true)
return;
if (keyIndex < 0)
{
requests.push([key, false]);
keyIndex = requests.length - 1;
}
loader = getLoader(key);
index = getLoaderIndex(loader);
if (index >= 0 && requestFunction != null)
{
requests[keyIndex][1] = true;
loaders[index][2] = true;
requestFunction(loader, key);
}
}
/**
* 获取loader对象
*/
private function getLoader(key:Object):EventDispatcher
{
var loader:EventDispatcher = null;
var i:int = 0;
// 在loaders中查找是否有空闲的loader
for (i = 0; i < loaders.length; i++)
{
if (loaders[i][2] == false)
{
loader = loaders[i][0];
loaders[i][1] = key;
break;
}
}
// loaders中无空闲loader则看是否可以新创建一个
if (loader == null && loaders.length < maxLoaderCount)
{
loader = createLoader();
loaders.push([loader, key, false]);
}
return loader;
}
/**
* 创建loader对象
*/
private function createLoader():EventDispatcher
{
var loader:EventDispatcher = null;
switch (loaderType)
{
case (RemoteDataLoader.URLLOADER):
loader = new URLLoader();
loader.addEventListener(Event.COMPLETE, loaderHandler);
loader.addEventListener(IOErrorEvent.IO_ERROR, loaderHandler);
loader.addEventListener(SecurityErrorEvent.SECURITY_ERROR, loaderHandler);
break;
case (RemoteDataLoader.HTTPSERVICE):
loader = new HTTPService();
loader.addEventListener(ResultEvent.RESULT, loaderHandler);
loader.addEventListener(FaultEvent.FAULT, loaderHandler);
break;
case (RemoteDataLoader.WEBSERVICE):
loader = new HTTPService();
loader.addEventListener(ResultEvent.RESULT, loaderHandler);
loader.addEventListener(FaultEvent.FAULT, loaderHandler);
break;
default:
break;
}
return loader;
}
/**
* 获取指定key在requests中的存放位置
*/
private function getKeyIndex(key:Object):int
{
var index:int = -1;
var i:int = 0;
for (i = 0; i < requests.length; i++)
{
if (requests[i][0] == key)
{
index = i;
break;
}
}
return index;
}
/**
* 获取指定loader在loaders中的存放位置
*/
private function getLoaderIndex(loader:EventDispatcher):int
{
var index:int = -1;
var i:int = 0;
if (loader == null)
return index;
for (i = 0; i < loaders.length; i++)
{
if (loaders[i][0] == loader)
{
index = i;
break;
}
}
return index;
}
//--------------------------------------------------------------------------
//
// Event handlers
//
//--------------------------------------------------------------------------
/**
* loader事件处理函数
*/
private function loaderHandler(event:Event):void
{
var result:Object = null;
var fault:Boolean = true;
var data:Object = null;
var index:int = -1;
var keyIndex:int = -1;
var i:int = 0;
if (event is ResultEvent)
{
data = (event as ResultEvent).result;
fault = false;
}
else
{
if (event.type == Event.COMPLETE)
{
data = (event.target as URLLoader).data;
fault = false;
}
}
// 如果成功返回结果并且存在resultFunction则调用resultFunction取得结果值
if (fault == false && resultFunction != null)
{
result = resultFunction(data);
if (grid)
{
grid.invalidateList();
grid.invalidateDisplayList();
}
}
// 向transformDictionary中添加结果值, 在loaders中当前loader设置空闲状态
// 并删除requests中的请求值
index = getLoaderIndex(event.target as EventDispatcher);
if (index >= 0)
{
transformDictionary.setKey(loaders[index][1], result);
loaders[index][2] = false;
keyIndex = getKeyIndex(loaders[index][1]);
if (keyIndex >= 0)
requests.splice(keyIndex, 1);
}
// 检查requests是否有未加载的请求, 如有, 则加载之
for (i = 0; i < requests.length; i++)
if (requests[i][1] == false)
loadRequest(requests[i][0]);
}
}
}
////////////////////////////////////////////////////////////////////////////////
//
// TransformDictionary
//
// 将Dictionary对象封装为本类的一个属性, 由此可以方便地用数组来创建TransformDictionary
// 主要用于编码-名称之类的数据显示
//
////////////////////////////////////////////////////////////////////////////////
package com.eccac.utils
{
import flash.utils.Dictionary;
public class TransformDictionary
{
//--------------------------------------------------------------------------
//
// Constructor
//
//--------------------------------------------------------------------------
/**
* Constructor
*/
public function TransformDictionary(array:Array = null,
weakKeys:Boolean = false)
{
super();
this.dictionary = new Dictionary(weakKeys);
this.weakKeys = weakKeys;
setData(array);
}
//--------------------------------------------------------------------------
//
// Variables
//
//--------------------------------------------------------------------------
/**
* Dictionary对象在对象键上使用"弱"引用
*/
private var weakKeys:Boolean = false;
/**
* Dictionary对象
*/
private var dictionary:Dictionary = null;
//--------------------------------------------------------------------------
//
// Methods
//
//--------------------------------------------------------------------------
/**
* 直接赋值
*/
public function setData(array:Array = null):void
{
var i:int = 0;
dictionary = new Dictionary(weakKeys);
if (array == null)
return;
for (i = 0; i < array.length; i++)
if (array[i] != null && array[i] is Array &&
(array[i] as Array).length >= 2)
dictionary[array[i][0]] = array[i][1];
}
/**
* 添加或设置键与值
*/
public function setKey(key:Object, value:Object):void
{
dictionary[key] = value;
}
/**
* 删除键与值
*/
public function deleteKey(key:Object):void
{
if (dictionary[key] != undefined)
delete dictionary[key];
}
/**
* 根据key获取值
*/
public function getValue(key:Object):*
{
return dictionary[key];
}
/**
* 通过key获取显示文本
* 如果指定的key不存在并且有key为null的元素, 则返回key为null的值的文本
*/
public function getDisplayText(key:Object):String
{
var text:String = "";
if (dictionary[key] != undefined)
if (dictionary[key] != null)
text = dictionary[key].toString();
else
if (dictionary[null] != undefined && dictionary[null] != null)
text = dictionary[null].toString();
return text;
}
}
}
2009-02-20
RemoteDataLoader
这个东西是用来干什么的呢?还真不太好解释。这么说吧,比如我们从服务器端得到了一个员工列表,字段有员工ID、姓名、部门ID,这时我们想显示部门名称而不是部门ID,而服务器端恰巧就有这么一个方法根据部门ID返回部门名称。我们可以这样做:来一个循环,比如取了10条数据,那么就循环10次,假设用HTTPService对象访问远程数据,那么就依次创建10个HTTPService,然后发送请求……这种方法我没有试过,但我想肯定会特别耗费资源。其实可以这样做,只创建较少的HTTPService,比如3个,然后让它们轮流来干活儿。这就是这个RemoteDataLoader类的主要作用了。我的代码其实是定义了一个类,继承AdvancedDataGridColumn,然后覆盖它的labelFunction,并给它加一个属性(RemoteDataLoader类型),在labelFunction中调用RemoteDataLoader的getResult方法取得结果。不过有两个问题:一是labelFunction只在表格初始化后调用一次,然后改变列宽或者拖动列时才会再次调用,但第一次调用时显示没有返回结果,因为这时候HTTPService正忙着访问服务器呢,需要多次调用labelFunction才会显示出结果;二是我访问google来做测试,maxLoaderCount只设了1个,已然都很慢了,而且发送请求时还会有假死现象,估计换成访问本地服务速度会快很多,还是推荐从服务端返回员工列表时直接返回部门名称,而不要再逐条请求。下面是部分代码:
订阅:
博文评论 (Atom)

没有评论:
发表评论