`
txf2004
  • 浏览: 7040338 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

Flex通信篇——Flex和外部进行异步通信

 
阅读更多

ExternalInterface.call的问题

请留意以下情景,要利用外部应用程序弹出文件选择窗体,并返回所选的文件路径。

使用ExternalInterface.call来实现,当用户60秒(Flex已经设置最长的等待时间)内未能够完成文件选择会弹出"1502"的错误,严重影响用户体现。

所以,一些比较耗时的操作(超过60s),或无法确定何时调用完成的方法(如上述),应该使用异步调用的方式,当方法执行完成后进行回调。

<![CDATA[

实现异步调用机制

Flex端

定义一个Dictionary,用来缓存回调的方法

private var m_AsyncDict:Dictionary;

定义OpenFileDialogAsync方法,用fscommand来实现,fscommand是单向的调用,不存在60秒超时的问题。

//弹出打开文件窗口,选择单个文件

public function OpenFileDialogAsync(title:String = "请选择1个文件", initFolder:String = "", filter:String = "", callbackString:Function = null):void

{

//创建异步ID

var id:String = mx.utils.UIDUtil.createUID();

//创建自定义异步请求

var request:String = "<args>";

request += "<arg>" + id + "</arg>";

request += "<arg>" + title + "</arg>";

request += "<arg>" + initFolder + "</arg>";

request += "<arg>" + filter + "</arg>";

request += "</args>";

//缓存回调方法

if (callbackString != null)

m_AsyncDict[id] = callbackString;

flash.system.fscommand(FLASH_TO_APP_OPEN_FILE_DIALOG_ASYNC, request);

}

定义并注册AsyncCallback和CancelAsyncCall方法,让外部应用程序能够响应异步回调或取消异步回调。

public function AsyncCallback(id:String, value:Object):void

{

if (m_AsyncDict[id])

{

//执行回调方法

m_AsyncDict[id](value);

delete m_AsyncDict[id];

}

}

public function CancelAsyncCall(id:String):void

{

if (m_AsyncDict[id])

{

delete m_AsyncDict[id];

}

}

if (ExternalInterface.available)

{

ExternalInterface.addCallback(APP_TO_FLASH_ASYNC_CALLBACK, AsyncCallback);

ExternalInterface.addCallback(APP_TO_FLASH_CANCEL_ASYNC_CALL, CancelAsyncCall);

}

EXE端

为ShockwaveFlashObject注册FSCommand事件,并添加事件处理的方法。

axShockwaveFlash1.FlashCall += new AxShockwaveFlashObjects._IShockwaveFlashEvents_FlashCallEventHandler(axShockwaveFlash1_FlashCall);

void axShockwaveFlash1_FSCommand(object sender, AxShockwaveFlashObjects._IShockwaveFlashEvents_FSCommandEvent e)

{

//请求e.args是自定义Xml格式

XmlDocument request = new XmlDocument();

request.LoadXml(e.args);

if (e.command == FLASH_TO_APP_OPEN_FILE_DIALOG_ASYNC)

{

//获取回调的键值

string asyncId = request.DocumentElement.ChildNodes[0].InnerText;

//获取窗体参数

string title = request.DocumentElement.ChildNodes[1].InnerText;

string initFolder = request.DocumentElement.ChildNodes[2].InnerText;

string filter = request.DocumentElement.ChildNodes[3].InnerText;

using (OpenFileDialog dlg = new OpenFileDialog())

{

dlg.Title = title;

dlg.InitialDirectory = initFolder;

dlg.Filter = filter;

if (dlg.ShowDialog() == DialogResult.OK)

{

AsyncCallback(asyncId, dlg.FileName);

}

else

{

CancelAsyncCall(asyncId);

}

}

}

}

定义2个方法调用Flex里注册的AsyncCallback和CancelAsyncCall方法。

//异步回调

public void AsyncCallback(string asyncId, string value)

{

StringBuilder sb = new StringBuilder();

sb.Append("<invoke name=/"").Append(APP_TO_FLASH_ASYNC_CALLBACK).Append("/" returntype=/"xml/">");

sb.Append("<arguments>");

sb.Append("<string>").Append(asyncId).Append("</string>");

sb.Append("<string>").Append(value).Append("</string>");

sb.Append("</arguments>");

sb.Append("</invoke>");

axShockwaveFlash1.CallFunction(sb.ToString());

}

//撤销异步回调

private void CancelAsyncCall(string asyncId)

{

StringBuilder sb = new StringBuilder();

sb.Append("<invoke name=/"").Append(APP_TO_FLASH_CANCEL_ASYNC_CALL).Append("/" returntype=/"xml/">");

sb.Append("<arguments>");

sb.Append("<string>").Append(asyncId).Append("</string>");

sb.Append("</arguments>");

sb.Append("</invoke>");

axShockwaveFlash1.CallFunction(sb.ToString());

}

完整代码

Flex端

LocalAPI.as

package

{

import flash.external.ExternalInterface;

import flash.system.fscommand;

import flash.utils.Dictionary;

import mx.utils.UIDUtil;

public class LocalAPI

{

//通讯命令定义

private static const FLASH_TO_APP_OPEN_FILE_DIALOG:String = "OpenFileDialog";

private static const FLASH_TO_APP_OPEN_FILE_DIALOG_ASYNC:String = "OpenFileDialogAsync";

private static const APP_TO_FLASH_ASYNC_CALLBACK:String = "AsyncCallback";

private static const APP_TO_FLASH_CANCEL_ASYNC_CALL:String = "CancelAsyncCall";

//Async dict

private var m_AsyncDict:Dictionary;

//Singleton static obj

private static var g_Instance:LocalAPI = null;

//获取LocalAPI单件实例

public static function get Instance():LocalAPI

{

if (g_Instance == null)

{

g_Instance = new LocalAPI();

}

return g_Instance;

}

public function LocalAPI()

{

if (g_Instance != null)

throw new Error("Singleton class. Please use Instance static filed.");

m_AsyncDict = new Dictionary();

if (ExternalInterface.available)

{

ExternalInterface.addCallback(APP_TO_FLASH_ASYNC_CALLBACK, AsyncCallback);

ExternalInterface.addCallback(APP_TO_FLASH_CANCEL_ASYNC_CALL, CancelAsyncCall);

}

}

//弹出打开文件窗口,选择单个文件(60s局限)

public function OpenFileDialog(title:String = "请选择1个文件", initFolder:String = "", filter:String = ""):String

{

if(!ExternalInterface.available) return null;

return ExternalInterface.call(FLASH_TO_APP_OPEN_FILE_DIALOG, title, initFolder, filter);

}

//异步通信

//弹出打开文件窗口,选择单个文件

public function OpenFileDialogAsync(title:String = "请选择1个文件", initFolder:String = "", filter:String = "", callbackString:Function = null):void

{

//创建异步ID

var id:String = mx.utils.UIDUtil.createUID();

//创建自定义异步请求

var request:String = "<args>";

request += "<arg>" + id + "</arg>";

request += "<arg>" + title + "</arg>";

request += "<arg>" + initFolder + "</arg>";

request += "<arg>" + filter + "</arg>";

request += "</args>";

//缓存回调方法

if (callbackString != null)

m_AsyncDict[id] = callbackString;

flash.system.fscommand(FLASH_TO_APP_OPEN_FILE_DIALOG_ASYNC, request);

}

public function AsyncCallback(id:String, value:Object):void

{

if (m_AsyncDict[id])

{

//执行回调方法

m_AsyncDict[id](value);

delete m_AsyncDict[id];

}

}

public function CancelAsyncCall(id:String):void

{

if (m_AsyncDict[id])

{

delete m_AsyncDict[id];

}

}

}

}

Demo.mxml

<?xml version="1.0" encoding="utf-8"?>

<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" fontSize="12">

<mx:Script>

private function GetFilePath():void

{

var path:String = LocalAPI.Instance.OpenFileDialog();

if (path != null)

_Path1.text = path;

}

//异步方式

private function GetFilePathAsync():void

{

LocalAPI.Instance.OpenFileDialogAsync("请选择1个文件", "", "", function(result:String):void

{

_Path2.text = result;

});

}

</mx:Script>

<mx:Button x="445.75" y="100" label="浏览1" click="GetFilePath()"/>

<mx:Button x="445.75" y="147" label="浏览2" click="GetFilePathAsync()"/>

<mx:Label x="71" y="102" text="文件路径"/>

<mx:TextInput x="188.25" y="100" width="249.5" id="_Path1"/>

<mx:TextInput x="188.25" y="147" width="249.5" id="_Path2"/>

<mx:Label x="71" y="149" text="文件路径(异步方式)"/>

<mx:Text x="71" y="196" width="459.75" height="213" id="_Trace"/>

</mx:Application>

EXE端

using System;

using System.Collections.Generic;

using System.ComponentModel;

using System.Data;

using System.Drawing;

using System.Text;

using System.Windows.Forms;

using System.Xml;

namespace WinFormDemo

{

public partial class Form1 : Form

{

//定义通信命令

private string FLASH_TO_APP_OPEN_FILE_DIALOG = "OpenFileDialog";

private string FLASH_TO_APP_OPEN_FILE_DIALOG_ASYNC = "OpenFileDialogAsync";

private string APP_TO_FLASH_ASYNC_CALLBACK = "AsyncCallback";

private string APP_TO_FLASH_CANCEL_ASYNC_CALL = "CancelAsyncCall";

private bool m_Init = false;

public Form1()

{

InitializeComponent();

}

private void Form1_Load(object sender, EventArgs e)

{

if (m_Init) return;

string swf = System.IO.Path.Combine(Application.StartupPath, "Demo.swf");

axShockwaveFlash1.FSCommand += new AxShockwaveFlashObjects._IShockwaveFlashEvents_FSCommandEventHandler(axShockwaveFlash1_FSCommand);

axShockwaveFlash1.FlashCall += new AxShockwaveFlashObjects._IShockwaveFlashEvents_FlashCallEventHandler(axShockwaveFlash1_FlashCall);

axShockwaveFlash1.Movie = swf;

m_Init = true;

}

void axShockwaveFlash1_FlashCall(object sender, AxShockwaveFlashObjects._IShockwaveFlashEvents_FlashCallEvent e)

{

//请求e.request是Xml格式,详细请查阅文档

XmlDocument request = new XmlDocument();

request.LoadXml(e.request);

string command = request.DocumentElement.Attributes["name"].Value;

if (command == FLASH_TO_APP_OPEN_FILE_DIALOG)

{

//获取窗体参数

string title = request.DocumentElement.ChildNodes[0].ChildNodes[0].InnerText;

string initFolder = request.DocumentElement.ChildNodes[0].ChildNodes[1].InnerText;

string filter = request.DocumentElement.ChildNodes[0].ChildNodes[2].InnerText;

using (OpenFileDialog dlg = new OpenFileDialog())

{

dlg.Title = title;

dlg.InitialDirectory = initFolder;

dlg.Filter = filter;

if (dlg.ShowDialog() == DialogResult.OK)

{

axShockwaveFlash1.SetReturnValue("<string>" + dlg.FileName + "</string>");

}

else

{

axShockwaveFlash1.SetReturnValue("<null/>");

}

}

}

}

void axShockwaveFlash1_FSCommand(object sender, AxShockwaveFlashObjects._IShockwaveFlashEvents_FSCommandEvent e)

{

//请求e.args是自定义Xml格式

XmlDocument request = new XmlDocument();

request.LoadXml(e.args);

if (e.command == FLASH_TO_APP_OPEN_FILE_DIALOG_ASYNC)

{

//获取回调的键值

string asyncId = request.DocumentElement.ChildNodes[0].InnerText;

//获取窗体参数

string title = request.DocumentElement.ChildNodes[1].InnerText;

string initFolder = request.DocumentElement.ChildNodes[2].InnerText;

string filter = request.DocumentElement.ChildNodes[3].InnerText;

using (OpenFileDialog dlg = new OpenFileDialog())

{

dlg.Title = title;

dlg.InitialDirectory = initFolder;

dlg.Filter = filter;

if (dlg.ShowDialog() == DialogResult.OK)

{

AsyncCallback(asyncId, dlg.FileName);

}

else

{

CancelAsyncCall(asyncId);

}

}

}

}

//异步回调

public void AsyncCallback(string asyncId, string value)

{

StringBuilder sb = new StringBuilder();

sb.Append("<invoke name=/"").Append(APP_TO_FLASH_ASYNC_CALLBACK).Append("/" returntype=/"xml/">");

sb.Append("<arguments>");

sb.Append("<string>").Append(asyncId).Append("</string>");

sb.Append("<string>").Append(value).Append("</string>");

sb.Append("</arguments>");

sb.Append("</invoke>");

axShockwaveFlash1.CallFunction(sb.ToString());

}

//撤销异步回调

private void CancelAsyncCall(string asyncId)

{

StringBuilder sb = new StringBuilder();

sb.Append("<invoke name=/"").Append(APP_TO_FLASH_CANCEL_ASYNC_CALL).Append("/" returntype=/"xml/">");

sb.Append("<arguments>");

sb.Append("<string>").Append(asyncId).Append("</string>");

sb.Append("</arguments>");

sb.Append("</invoke>");

axShockwaveFlash1.CallFunction(sb.ToString());

}

}

}

系列索引

Flex通信篇——Flex和外部应用程序进行通信

Flex通信篇——Flex和外部进行异步通信

Flex通信篇——Flex键盘组合键

Flex通信篇——构建企业级HTTP通信层

]]>
分享到:
评论

相关推荐

    FLEX入门篇——日期的格式化

    本文将围绕“FLEX入门篇——日期的格式化”这一主题,深入探讨如何在Flex中处理和格式化日期。日期格式化在任何应用程序中都是常见的需求,尤其是在展示或存储用户友好的时间信息时。 首先,我们要了解Flex中处理...

    flex调用swf——swf可以转成具体的对象,而非MovieClip

    总之,通过正确的ActionScript编程和项目配置,我们可以将外部SWF资源作为具体对象在Flex应用中使用,从而极大地扩展了我们的功能和灵活性。这在处理第三方组件或者复用已有代码库时尤其有用。为了获取更多具体的...

    ArcGIS Flex 例子——源码(强烈推荐)

    FlexViewer 使用 ArcGIS Server 提供的地图服务,通过 SOAP 或 REST API 与服务器进行通信。学习如何在 Flex 中添加和使用地图服务是掌握 ArcGIS Flex 的关键步骤。 6. **调试与开发** 利用 Flex Builder 或其他 ...

    创建第一个Flex应用——编码模式

    创建第一个Flex应用——编码模式创建第一个Flex应用——编码模式创建第一个Flex应用——编码模式

    创建第一个Flex应用——设计模式

    创建第一个Flex应用——设计模式创建第一个Flex应用——设计模式创建第一个Flex应用——设计模式

    Flex与Java实现通信

    这些类将通过BlazeDS与Flex前端进行通信。 #### 四、使用BlazeDS进行Flex与Java通信 完成上述步骤后,就可以开始使用BlazeDS进行Flex与Java之间的通信了。具体的通信流程包括: 1. **定义服务接口**:在Java中...

    精通Flex 3.0——基于ActionScript 3.0实现_源代码

    《精通Flex 3.0——基于ActionScript 3.0实现》一书源代码。 Flex 3.0 ActionScript 3.0源代码 Flex 3.0源代码。 --------------------------- 第1篇 Flex技术概述 第1章 Flex概述 3 1.1 Flex简介 3 1.2 Flex...

    flex布局项目——携程在线首页(原生轮播图效果).zip

    携程在线首页。适合零基础入门的人使用的demo,对布局这块有不错的...采用的是flex布局使用了原生js实现的tab栏切换等。自己可以通过swiper插件或者TouchSlide插件以及bootstrap框架来替换!可以把这个demo进行更改。

    Flex通信-Java服务端通信实例

    Flex通信-Java服务端通信实例主要探讨的是在Web开发中,如何使用Adobe Flex与Java后端进行交互。Flex是一款强大的富互联网应用程序(RIA)开发工具,它可以创建动态、交互式的用户界面,而Java则通常作为服务器端的...

    FLEX资源——FLEX数据绑定专题(中文PDF)

    数据绑定是Flex中一个核心的概念,它简化了用户界面与应用程序数据之间的通信,使得数据的更新能够自动反映在UI上,反之亦然。 在Flex中,数据绑定是一种声明式编程方式,开发者无需编写复杂的事件处理代码,即可...

    java+flex通信源码

    5. **事件驱动编程**:Flex和Java之间的通信通常是异步的,基于事件的。当服务器响应到达时,会触发特定的事件,客户端可以通过监听这些事件来处理结果。 6. **数据管理**:在Java后端,可能会使用Spring、...

    FLEX技术之四——界面布局和导航

    flex界面布局和导航,flex各个控件的使用,布局的容器和布局的空间,详细的代码演示

    flex与java通信

    在Flex和Java之间进行通信时,通常会用到两种主要技术:AMF(Action Message Format)和SOAP(Simple Object Access Protocol)。AMF是一种二进制协议,用于提高数据传输效率,而SOAP则是基于XML的标准协议,更适用...

    Flex游戏——水果乐园(含源码)

    Flex游戏——水果乐园(含源码) 游戏介绍: * 通过键盘方向键控制小熊(游戏主人翁)在迷宫内行走,在指定时间内拾取所有水果就通过游戏否不通过。 * 每次拾取水果必须正确回答问题才能够真正获取水果。 * 游戏中有...

    flex 异步加载tree

    根据给定的信息,我们可以深入探讨Flex中的异步加载Tree组件的相关知识点。 ### 一、Flex与AsyncTree组件 #### 1. Flex简介 Flex是一种开源的框架,用于构建跨平台的桌面应用程序和移动应用程序。它提供了强大的...

    flex与服务端通信的as封装源码(同步、异步两种方式)

    这篇资料提供了一套AS(ActionScript)源码,用于实现Flex客户端与服务端的交互,支持同步和异步两种通信方式,且采用HTTPService进行封装,避免了对BlazeDS的依赖。主要知识点包括: 1. **Flex与服务端通信**:...

Global site tag (gtag.js) - Google Analytics