|
在移动平台的WebApp开发中,跨域问题一直是一个比较重要的环节。尽管Ajax的跨域在某些层面带来了不少安全隐患,但同时也彻底放开了传统Ajax的限制。。目前大量的移动Web开发框架都已从不同角度提出了自己的解决方法,效果不一。。
本篇重点介绍Rexsee内置的Ajax对象,通过RexseeAjax对本地的页面进行动态注值,是不是很爽啊~
这就是我们使用Rexsee时可以使用的独特程序架构——B/C/S,即页面和资源文件本地化,通过ajax从服务器获取数据。
此种架构有3种好处:其一,页面读取和加载速度的优化。其二,流量的优化。其三,用户体验的优化。
先来了解一下rexseeajax对象。此对象包含3个方法和3个事件:前2个方法是异步取值,最后一个方法则是同步取值。事件的对应在手册中有相应的说明,这里就不再叙述了。
使用rexseeajax的时候需要注意:
在rexsee 提供的3个ajax对象函数中,submit和submitWithCallback函数在回调函数(事件)中返回的字串(response)是需要用unescape解码的,即直接alert(response)会看到乱码,需要alert(unescape(response))才可以看到正常的字串。但在syncSubmit函数中,返回字串则不需要unescape。
对于submit和syncSubmit,这两个函数是在读取数据的时候默认调用的旋转进度框,如果想在请求数据时不使用旋转进度框,那么我们需要使用submitWithCallback,当然我想使用其他进度框也可以在其的触发事件onAjaxProgressChanged中编写。
为什么要额外提到这里,因为在数据较多的情况下,使用带默认进度框的ajax方法会使得用户体验变得很不好,而使用没有进度框ajax方法,则可以自己定义用户等待的界面,比如一个GIF动画等等。同时,可以避免在页面切换时带来的延迟等待(因为我们一般都把页面本地化,页面的读取都是从本地读取,而数据获取则是从网络)。
大家现在来看个小例子:
图片:http://www.rexsee.com/imagecache/bbs/11-10-09/1318131354.png
图片:http://www.rexsee.com/imagecache/bbs/11-10-09/1318131430.png
图片:http://www.rexsee.com/imagecache/bbs/11-10-09/1318131487.png
无进度框代码
function checkLogin(){
var name=document.getElementById('username').value;
var password=document.getElementById('password').value;
rexseeAjax.submitWithCallback('http://www.fuwu800.com/yezhenqing/ajaxTest/check.php','name='+name+'&password='+password,'gb2312');
}
function onAjaxReturned(ajaxUrl,response)
{
var temp=eval("("+unescape(response)+")");
temp=temp.result;
if(temp==1){
rexseeBrowser.go('test.html');
}else if(temp==0){
rexseeDialog.alert('消息框','登录失败!');
}
}
有进度框代码
function checkLogin(){
var name=document.getElementById('username').value;
var password=document.getElementById('password').value;
var temp=eval("("+ rexseeAjax.syncSubmit('http://www.fuwu800.com/yezhenqing/ajaxTest/check.php','name='+name+'&password='+password,'gb2312')+")");
temp=temp.result;
if(temp==1){
rexseeBrowser.go('test.html');
}else if(temp==0){
rexseeDialog.alert('消息框','登录失败!');
}
}
通过ajax来检查我们的用户名和密码是否合法,合法的话进入数据页面,否则提示失败。数据页面获取代码:
无进度框代码
rexseeAjax.submitWithCallback('http://www.fuwu800.com/yezhenqing/ajaxTest/a.html','','gb2312');
function onAjaxReturned(ajaxUrl,response)
{
document.getElementById("contents").innerHTML="";
var temp=unescape(response);
var test=eval("("+temp+")");
for(var i=0;i<test.length;i++){
document.getElementById("contents").innerHTML+="<li>"+test.firstName+"."+test.lastName+"</li>";
}
}
function onAjaxProgressChanged(ajaxUrl,totalSize,downloadedSize){
document.getElementById("contents").innerHTML="<li>Loading...</li>";
}
有进度框代码
window.onRexseeReady=function(){
document.getElementById("contents").innerHTML="";
var test=eval("("+rexseeAjax.syncSubmit('http://www.fuwu800.com/yezhenqing/ajaxTest/a.html','','gb2312')+")");
for(var i=0;i<test.length;i++){
document.getElementById("contents").innerHTML+="<li>"+test.firstName+"."+test.lastName+"</li>";
}
}
大家可以将数据页面的内容加大,看看在2中不用的请求形式下,等待程序的长短。那么以后自己的程序该如何去设计,都应该了然于胸了。
数据格式都是标准的json数据和数组,使用eval('('+json+')')方法转换为对象即可方便使用。
最后把RexseeAjax的源码贴出,供参考。。有点多~~
/*
* Copyright (C) 2011 The Rexsee Open Source Project
*
* Licensed under the Rexsee License, Version 1.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.rexsee.com/CN/legal/license.html
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package rexsee.core.transportation;
import java.io.DataOutputStream;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.SocketTimeoutException;
import java.net.URL;
public class RexseeAjax implements JavascriptInterface {
public static final String INTERFACE_NAME = "Ajax";
@Override
public String getInterfaceName() {
return mBrowser.application.resources.prefix + INTERFACE_NAME;
}
@Override
public JavascriptInterface getInheritInterface(RexseeBrowser childBrowser) {
return new RexseeAjax(childBrowser);
public static final String EVENT_ONAJAXPROGRESSCHANGED = "onAjaxProgressChanged";
public static final String EVENT_ONAJAXRETURNED = "onAjaxReturned";
public static final String EVENT_ONAJAXTIMEOUT = "onAjaxTimeout";
public static final int AJAX_PROGRESS_DONE = 1;
public static abstract class AjaxProgressListener {
public abstract void run(String ajaxUrl, int status, int totalSize, int downloadedSize, String ajaxResponse, Runnable stopTheAjax);
}
private final RexseeBrowser mBrowser;
private String syncAjaxRtn = null;
public RexseeAjax(RexseeBrowser browser) {
mBrowser = browser;
public void submit(String url, final String postData, final AjaxProgressListener progressListener, final String encode, final boolean callbackJs) {
final String ajaxUrl = mBrowser.urlListeners.getAbsoluteUrl(url);
Uri uri = Uri.parse(ajaxUrl);
if (uri == null) {
if (progressListener != null) progressListener.run(ajaxUrl, if (scheme == null || (!scheme.equals("http") && !scheme.equals("https"))) {
if (progressListener != null) progressListener.run(ajaxUrl, AJAX_PROGRESS_EXCEPTION, 0, 0, "Invalid url.", null);
mBrowser.exception(getInterfaceName(), url + ":Invalid url.");
return;
}
if (!mBrowser.domainWhiteList.isValidUrl(ajaxUrl)) {
if (progressListener != null) progressListener.run(ajaxUrl, AJAX_PROGRESS_EXCEPTION, 0, 0, "Url not allowed.", null);
mBrowser.exception(getInterfaceName(), url + ":Url not allowed.");
return;
stop = true;
if (progressListener != null) progressListener.run(ajaxUrl, AJAX_PROGRESS_EXCEPTION, 0, 0, "User canceled.", null);
}
};
@Override
public void run() {
int timeout = mBrowser.application.getTimeout() * 1000;
try {
byte[] postBytes = new String(postData.getBytes(), encode).getBytes(encode);
if (progressListener != null) progressListener.run(ajaxUrl, AJAX_PROGRESS_CONNECTING, 0, 0, null, stopRunnable);
URL url = new URL(ajaxUrl);
CookieManager cookieManager = CookieManager.getInstance();
String cookie = cookieManager.getCookie(ajaxUrl);
if (cookie != null) {
urlConnection.setRequestProperty("Cookie", cookie);
//After urlConnection.connect(); could retrieve sessionId with urlConnection.getHeaderField("Set-Cookie");
}
urlConnection.setRequestProperty("User-Agent", mBrowser.getSettings().getUserAgentString());
urlConnection.setRequestProperty("Content-Length", "" + postBytes.length);
urlConnection.connect();
DataOutputStream dos = new DataOutputStream(urlConnection.getOutputStream());
dos.write(postBytes);
dos.flush();
dos.close();
if (cookieManager.acceptCookie()) {
////Set session cookie
+ ";";
} else {
}
}
if (sessionCookie != "") cookieManager.setCookie(ajaxUrl, cookieVal);
}
InputStream inputStream = urlConnection.getInputStream();
int totalSize = urlConnection.getContentLength();
int downloadedSize = 0;
byte[] buffer = new byte[1024];
int bufferLength = 0;
String rtn = "";
while ((bufferLength = inputStream.read(buffer)) > 0 && !stop) {
rtn += new String(buffer, 0, bufferLength, encode);
downloadedSize += bufferLength;
if (progressListener != null) progressListener.run(ajaxUrl, AJAX_PROGRESS_ONGOING, totalSize, downloadedSize, rtn, stopRunnable);
}
if (!stop) {
if (progressListener != null) if (progressListener != null) progressListener.run(ajaxUrl, AJAX_PROGRESS_TIMEOUT, 0, 0, String.valueOf(timeout), null);
if (callbackJs) mBrowser.eventList.run(EVENT_ONAJAXTIMEOUT, new String[]{ajaxUrl, String.valueOf(timeout)});
}
} catch (Exception e) {
if (!stop) {
if (progressListener != null) progressListener.run(ajaxUrl, AJAX_PROGRESS_EXCEPTION, 0, 0, e.getLocalizedMessage(), null);
mBrowser.exception(getInterfaceName(), ajaxUrl + ":" + e.getLocalizedMessage());
}
}
}
}.start();
}
//JavaScript Interface
public void sendMessage(final String ajaxUrl, final String postData) {
submit(ajaxUrl, postData, null, "UTF-8", false);
}
public void submit(String ajaxUrl, String postData, final String encode) {
if (cancelable) {
mBrowser.progressDialog.showWithRunnable(RexseeLanguage.PROGRESS_CONNECT, stopTheAjax);
} else {
mBrowser.progressDialog.show(RexseeLanguage.PROGRESS_CONNECT);
}
} else if (status == AJAX_PROGRESS_TIMEOUT) {
mBrowser.progressDialog.hide();
} else if (status == AJAX_PROGRESS_EXCEPTION) {
mBrowser.progressDialog.hide();
} else if (status == AJAX_PROGRESS_ONGOING) {
String progress = (totalSize < 0) ? "" : (downloadedSize * 100 / totalSize) + "%";
if (cancelable) {
mBrowser.progressDialog.showWithRunnable(RexseeLanguage.PROGRESS_ONGOING + "......" + progress + " ", stopTheAjax);
} else {
mBrowser.progressDialog.show(RexseeLanguage.PROGRESS_ONGOING + "......" + progress + " ");
}
} else if (status == AJAX_PROGRESS_DONE) {
mBrowser.progressDialog.hide();
}
}
}, encode, true);
}
public void submitWithCallback(String ajaxUrl, String postData, final String encode) {
submit(ajaxUrl, postData, new AjaxProgressListener() {
@Override
public void run(String ajaxUrl, int status, int totalSize, int downloadedSize, String ajaxResponse, Runnable stopTheAjax) {
mBrowser.eventList.run(EVENT_ONAJAXPROGRESSCHANGED, new String[]{ajaxUrl, String.valueOf(totalSize), String.valueOf(downloadedSize)});
}
}, encode, true);
}
public String syncSubmit(String url, final String postData, final String encode) {
return syncSubmit(url, postData, encode, true, true);
}
public String syncSubmit(String url, final String postData, final String encode, final boolean showProgress, final boolean cancelable) {
syncAjaxRtn = null;
submit(url, postData, new AjaxProgressListener() {
@Override
public void run(String ajaxUrl, int status, int totalSize, int downloadedSize, String ajaxResponse, final Runnable stopTheAjax) {
if (status == RexseeAjax.AJAX_PROGRESS_CONNECTING) {
if (cancelable) {
if (showProgress) mBrowser.progressDialog.showWithRunnable(RexseeLanguage.PROGRESS_CONNECT, stopTheAjax);
} else {
if (showProgress) mBrowser.progressDialog.show(RexseeLanguage.PROGRESS_CONNECT);
}
} else if (status == RexseeAjax.AJAX_PROGRESS_TIMEOUT) {
syncAjaxRtn = RexseeApplication.EXCEPTION_PREFIX + ajaxResponse;
} else if (status == RexseeAjax.AJAX_PROGRESS_EXCEPTION) {
syncAjaxRtn = RexseeApplication.EXCEPTION_PREFIX + ajaxResponse;
} else if (status == RexseeAjax.AJAX_PROGRESS_ONGOING) {
String progress = (totalSize < 0) ? "" : (downloadedSize * 100 / totalSize) + "%";
if (cancelable) {
if (showProgress) mBrowser.progressDialog.showWithRunnable(RexseeLanguage.PROGRESS_ONGOING + "......" + progress + " ", stopTheAjax);
} else {
if (showProgress) mBrowser.progressDialog.show(RexseeLanguage.PROGRESS_ONGOING + "......" + progress + " ");
}
} else if (status == RexseeAjax.AJAX_PROGRESS_DONE) {
syncAjaxRtn = ajaxResponse;
}
}
}, encode, false);
while (syncAjaxRtn == null) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
}
}
if (showProgress) mBrowser.progressDialog.hide();
return syncAjaxRtn;
}
} |
|