Habitat Framework

专注于Java EE企业级开发
posts - 13, comments - 81, trackbacks - 0, articles - 5
  BlogJava :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理

2007年10月12日

Nokia在Maxis推广Widget的时候告诉我Widget只能在S603.2上运行,所有S603.0系列手机可以通过软件升级来支持这个新功能

Baidu一把,发现一大把人在说不能升级到S603.2,那不和Nokia的说法矛盾,Google一把Nokia software upgrade,找到一个自动更新程序
连上手机,可以自己帮你识别你的电话是否有最新软件升级可用,花了10多分钟就下载完114Mb的升级文件,然后又花了5分钟刷机成功,开机后感觉速度没有太大提升,反而铃声没有以前清脆了,我一款短信铃声以前听起来高音非常不错,现在听有爆音了.......马上测试了下我自己开发的Widget,果然可以识别并提示安装,装好了就和普通的Symbian Application一样,不错,又有得玩了........

但是由于一直没有查到S60的版本查看方法,所以我始终不知道我到底是不是升级到了3.2,如果有人知道,麻烦留言告诉一声

posted @ 2008-07-23 12:44 Kerwin Weng 阅读(293) | 评论 (0)编辑 收藏

好像国内对Adobe的新产品AIR反应还不多,我个人试用了下觉得其实用处还是很大的,于是我就抛砖引玉写一篇相关介绍文章吧

AIR其实是一套框架和一个VM,它允许用户把Javascript,HTML,CSS集成到统一的客户端,在用户桌面运行,避免了浏览器差异,并且实现了跨平台的通用性,同时又对Javascript功能进行了很多扩展,比如读取本地磁盘文件,做跨域的远程访问,使用多媒体文件等等(相信是flash的底层在支持),相对于两年前的Flex,AIR在RIA领域无疑又是一个跨越,
想象一下以后我们可以用JS+HTML+CSS来写基于http的远程且防火墙安全的C/S应用了,还是蛮爽吧
Demo在这里:http://labs.adobe.com/showcase/air/?promoid=BJXTF
用JS来写应用的文档在这里:http://livedocs.adobe.com/labs/air/1/devappshtml/


Adobe AIR出新版SDK后,出乎意料的是很多之前的Demo不能跑了,会出"parsing disallowed"
,原因就是adobe换用了新的安全框架,禁止掉了Javascript中某些可能对其框架做出安全威胁的API,比如说JSON的命根--eval

Adobe的官方解释是在AIR2禁止掉了类似eval这种动态代码加载技术在其Application sandbox中的运行,解决办法是把你有eval的应用移到Browse sandbox中执行,所谓的Browse sandbox意思是你的应用主页面是通过application.xml中配置的根页面来用iframe引入的,在iframe引入的页面中你就可以做eval,而把其他如跨域查询等AIR提供的高级API操作放到根页面中去做,然后通过一个parent/childSandboxBridge来做互相引用和传递数据的桥梁,
但是同时你在iframe中的js也不能直接使用AIR所提供的一些高级API,比如air.trace().原文的解释在这里 ,Adobe甚至还写了一篇文章来鼓吹这种方式其实更符合设计模式--根页面负责数据传递,iframe页面负责业务逻辑.但是无论如何这篇文章作为Browse sandbox的入门来讲还是很值得细读的

于是结合自己当前的实际需要,我写了一个批量查询airasia.com机票的小工具,因为airasia从来都是打广告说从多久到多久,从那里飞到那里才几块MYR! 就是这个"起"字相当关键......直接造成每次我去查的时候发现因为"已经快满坐"了,所以价格和平时的一样,甚至更高,听同事说他们都是先一天一天去查看哪天便宜就赶快预定,太辛苦了吧,那我要查2007-11-05到2008-01-31日的机票要花多少时间啊,而且不查到最后一天还不知道是不是最便宜的,嘲笑他们原始之后我就决定自己写个工具来查

所以我写的第一个AIR应用就是这个AirAsiaTicketsSearch,可以批量查询某个时间段去和某个时间段回的所有机票,并且把机票价格用jQuery.tablesort给排序出来,并且用jQuery.tablesort.page做了分页(说句题外话,jQuery的tablesort确实很强大,但是在排序"1,280.00 CNY"这种数据的时候还是有问题).另外开发环境值得一说,无论是eclipse+aptana或者aptana standalone都一样的,aptana就是一个Eclipse的RCP,关键就是aptana真的是很好用的工具,目前不仅支持AIR,而且还支持开发Apple iPhone的应用,只是专业版要收费.....

后面给出截图,
结果发现昨天还有295.99的机票,到了今天就涨到349.99了-_-!


posted @ 2007-11-05 20:39 Kerwin Weng 阅读(3792) | 评论 (7)编辑 收藏

几个月前就想弄明白什么是闭包,听名字多神奇,而且犀牛书上好像也没有讲到,baidu出来的结果倒是很多很准确,但是看着那些牛人们翻译的英文文章,讲了上千字我还是没有明白什么是闭包,遇到复杂的地方没法翻译还只能引用原文来解释,本来我的FF受某个插件影响开CSDN不仅慢还会停止响应10多秒,我都是忍痛点下CSDN的连接,结果看到这种垃圾文章真是让人愤怒,写了一大堆,最后还是不能让人明白他到底想要解释什么是闭包,还是炫耀他对技术的理解,还是要满足他对翻译的狂热.

结果今天终于看到一篇Morris Johns的文章,用了不到5分钟就把闭包是什么讲的清清楚楚,比如文章中有一句话:
In JavaScript, if you use the function keyword inside another function, you are creating a closure.

妈的,还有比这更简单的解释吗,为什么那些国内所谓的牛人就是写不出这种平实的话,就非要浪费自己和别人的时间讲一堆貌似浮云的定义,我觉得他们真的该思考下自己写技术文章的目的,是为了在传递知识,还是在满足自己的虚荣,如果是后者,建议直接在Tag中注明"自慰贴",免得浪费大家的时间.

在后面的文章中,作者列举了很多生动的例子,每个例子后面的解释都非常平实,没有任何为了表现自己能力的华丽辞藻,通过他的例子,我很快理解的闭包的特点,可以用来做什么,前后不到30分钟,回想我几个月前光是找合适的解释就找了近一个小时.

当我对闭包的特点已经谙熟于心后,作者再开始讲一些抽象的定义,让人感觉没有一点障碍,就如作者自己的话:
If everything seems completely unclear then the best thing to do is to play with the examples. Reading an explanation is much harder than understanding examples. My explanations of closures and stack-frames etc are not technically correct - they are gross simplifications intended to help understanding. Once the basic idea is grokked, you can pick up the details later.

最后给出那篇文章的地址,相信不懂闭包的人也能像我一样很快就理解,同时也希望大家看完后别忘了别人踏踏实实写技术文章的态度
http://www.javascriptkit.com/javatutors/closures.shtml

posted @ 2007-10-18 13:28 Kerwin Weng 阅读(1575) | 评论 (14)编辑 收藏

最近写AJAX的应用遇到很多需要丰富的Javascript集合的地方,可惜javascript没有Java的Collection那么强大的集合类,于是打算自己尝试写一个模拟Set的API,结果写出来的模拟类和Set有点不同,有一个优势--可以有序取单个对象,但也有一个劣势,就是删除单个对象需要遍历该集合,由于我的应用不大可能用到单个删除,所以我暂时还没有想到一种数据结构可以实现不遍历的单个对象删除,又能满足现有的API都高效完成,如果谁有更好的代码来实现请回复

目前想到可以实现的方法:

add(o);
addAll(array)
contain(o);
get(int);
getAll();
sort(comparator); //传进去的是一个fn,还没有写例子....
size();
remove();
reverse();


基本数据结构是两个数组,一个是index数组,数组下标连续,用来存放第二个数组的下标,另一个是存放对象的数组,不连续,下标是对象的id或者对象中其他任何可以转换成唯一Integer的Field(Set也要求放进去的对象必须要有hashCode嘛,不然没法区别第一个和第二个)

实现的API:
function Collection(){
    this.chain=new Array();
    this.table=new Array();
}
Collection.prototype.get=function(i){
    return this.table[this.chain[i]];
}
Collection.prototype.add=function(o){
    this.table[o.id]=o;
    this.chain.push(o.id);
}
Collection.prototype.addAll=function(array){
    for(var _i=0;_i<array.length;_i++){
        this.add(array[_i]);
    }
}
Collection.prototype.contain=function(o){
    if(this.table[o.id]){
        return true;
    }else{
        return false;
    }
}
Collection.prototype.getAll=function(){
    tempList=new Array();
    for(var _i=0;_i<this.chain.length;_i++){
        tempList.push(this.table[this.chain[_i]]);
    }
    return tempList;
}
Collection.prototype.sort=function(comparator){
    this.chain.sort(comparator);
}
Collection.prototype.remove=function(o){
    var _var = this.chain;
    for(var _i=0;i<this.chain.length;i++){
        if(this.table[this.chain[_i]].id==o.id){
            this.table[this.chain[_i]]=null;
            this.chain.splice(_i,1);
            return;
        }
    }
}
Collection.prototype.size=function(){
    return this.chain.length;
}
Collection.prototype.reverse=function(){
    this.chain.reverse();
}
目前还有一个addAll方法也是暂时没有想到有什么不用遍历的好的实现

前同事提供了一种完全和Set一样的实现,效率满高
function Map(){
    this.obj = {};
    this.count = 0;
}

Map.prototype.put = function(key, value){
    var oldValue = this.obj[key];
    if(oldValue == undefined){
        this.count++;
    }
    this.obj[key] = value;
    return oldValue;
}

Map.prototype.get = function(key){
    return this.obj[key];
}

Map.prototype.remove = function(key){
    var oldValue = this.obj[key];
    if(oldValue != undefined){
        this.count--;
        delete this.obj[key];
    }
    return oldValue;
}

Map.prototype.size = function(){
    return this.count;
}

function Set(getKey){
    this.map = new Map();
    this.getKey = getKey;
}

Set.prototype.add = function(value){
    var key = this.getKey(value);
    this.map.put(key, value);
}

Set.prototype.remove = function(value){
    var key = this.getKey(value);
    this.map.remove(key);
}
Set.protorype.getAll=function(){
    tempArray=new Array();
    for(var i in this.obj){
       tempArray.push(i);
    }
    return tempArray;
}

Set.prototype.size = function(){
    return this.map.size();
}

还有一个朋友的实现和我最初的差不多,但是remove方法相当有创意,用正则表达式来删除
Collection.prototype.remove=function(o){
    var _var = this.chain;
    this.table[o.id]=null;
    var re = new RegExp("(^["+o.id+"]$)|(^["+o.id+"][,])|([,]["+o.id+"]$)","g");
    var s = "["+this.chain.toString().replace(re,"").replace(","+o.id+",",",")+"]";
    this.chain=eval(s)
}

有人回复说需要添加做验证,我觉得不必了,如果添加的值和之前的一样就直接替换好了,如果希望不被replace,直接在添加新对象之前用contain判断一次就可以了,毕竟在我的实现中已不是完全在模拟Set了,目前更倾向于设计一个更高效和强大的集合类

posted @ 2007-10-12 11:46 Kerwin Weng 阅读(3534) | 评论 (2)编辑 收藏