前些天去參加了Google的開(kāi)發(fā)日活動(dòng),由于之后直接就去郊區(qū)所以一直沒(méi)有時(shí)間寫(xiě)blog來(lái)談?wù)劯邢搿J紫仁莋oogle的OpenSocial,進(jìn)入大廳簽到之后轉(zhuǎn)角過(guò)去就是個(gè)大網(wǎng)站的展臺(tái),每個(gè)柱子的一面是一個(gè)網(wǎng)站,都是OpenSocial的合作網(wǎng)站,有聚友,天際,天涯等。有幸跟聚友的CTO譚曉生先生和天際網(wǎng)的CTO郭應(yīng)壽先生聊了聊OpenSocial使用中的益處和遇到的問(wèn)題,感覺(jué)OpenSocial目前還是不太成熟,對(duì)比FB來(lái)說(shuō)還有一定的差距,比如沒(méi)有照片處理等等問(wèn)題。而且我始終有一種感覺(jué),OpenSocial是一個(gè)google的標(biāo)準(zhǔn),但是各大網(wǎng)站在使用OpenSocial的時(shí)候幾乎都會(huì)加上自己的擴(kuò)展,這樣下去,最終OpenSocial統(tǒng)一平臺(tái)的目標(biāo)很難實(shí)現(xiàn),因?yàn)閮蓚€(gè)網(wǎng)站的Gidget幾乎不能通用,這些問(wèn)題OpenSocial的合作網(wǎng)站跟Google也在討論中。另外得到的消息是,OpenSocial可能也會(huì)考慮出一套XXml,規(guī)范化OpenSocial的使用,并借此加強(qiáng)安全性。
稍后的OpenSocial專題topic中了解到了更多有關(guān)OpenSocial的信息,主要是Shindig了, 前一天還在跟白衣提議用ss做一個(gè)類似Shindig的東西,主要是做一個(gè)OpenSocial的實(shí)現(xiàn),當(dāng)時(shí)就想這玩意估計(jì)有了,但是沒(méi)想到是host到apache了,在apache的孵化器中大家可以自己找找。會(huì)議的時(shí)候逮住了一個(gè)google的人問(wèn)了一堆問(wèn)題,過(guò)后才知道原來(lái)是google中國(guó)sns的負(fù)責(zé)人。
最大的收獲實(shí)在是太意外了,在中午休息的時(shí)候,走過(guò)過(guò)道到樓下吃飯,突然發(fā)現(xiàn)一個(gè)熟悉的身影坐在角落里一個(gè)人在玩電腦,我暈是Andy Rubin,Android的老大。居然就坐在那里,而且旁邊的人沒(méi)有人在意他,要知道聽(tīng)android topic的人可不少呀,居然每一個(gè)人認(rèn)出他來(lái)的。我叫了朋友確認(rèn)一下,準(zhǔn)備上前打招呼。剛上去打了個(gè)招呼,握了個(gè)手,又來(lái)了一個(gè)人,他一下認(rèn)出Andy,并且跟Andy簡(jiǎn)短的交談了一下。我提議先照個(gè)相,照相后簡(jiǎn)短聊下那個(gè)人就走了。過(guò)后Andy說(shuō)那個(gè)人就是Google中國(guó)負(fù)責(zé)android的老大邸爍博士,我狂暈呀兩位老大都讓我給碰上了。稍候跟Andy聊了一下Android的發(fā)展,隨后他掏出一個(gè)android的原型機(jī),就是google IO大會(huì)上的那種機(jī)器。這里要說(shuō)明的是,不管在模擬器上android的表現(xiàn)如何,在真機(jī)上你的體驗(yàn)絕對(duì)絕對(duì)是不一樣的,太COOL了。尤其是第二屏的widget效果,還有那個(gè)street view效果,真機(jī)拿在手上體驗(yàn)就是不一樣呀~~~~ 隨后又了解到了一些android目前的發(fā)展情況,這里可以告訴大家的是,android是絕對(duì)值得期待的~!!!
經(jīng)過(guò)兩天的努力,終于在Android上面跑起來(lái)MSN了。現(xiàn)在實(shí)現(xiàn)了基本的聊天功能,打算陸續(xù)的把其他功能完善,萬(wàn)事開(kāi)頭難,相信以后的工作會(huì)很順利。
Gtalk的功能由于有官方支持,早就弄了跟這個(gè)差不多的版本。
另外,這個(gè)軟件目前是以插件的形式開(kāi)發(fā),多一個(gè)協(xié)議就是多一個(gè)apk,實(shí)現(xiàn)一些intent即可。官方的IM包里面有很多支持,可惜文檔沒(méi)有提及。

Android中文論壇原帖
今天看到Air1.0和Ext2.0.2的發(fā)布消息,很是興奮,要知道Ext的每個(gè)版本升級(jí)都是很實(shí)惠的。
Ext2.0.2的這次升級(jí)主要是針對(duì)Air的支持,看來(lái)他們的關(guān)系是越來(lái)越近了,我也借機(jī)小試了一下Air。
簡(jiǎn)單說(shuō)說(shuō)Air的開(kāi)發(fā)過(guò)程:
1.先要下載jre 和 airSDK
2.jre就不說(shuō)了,airSDK也是簡(jiǎn)單的解壓一下便可。
可以看看SDK下面的bin目錄,一共倆文件,一個(gè)adl一個(gè)adt,adl是用來(lái)測(cè)試的,adt使用編輯發(fā)布的(ADT怎么讓我想起來(lái)android了)
3.創(chuàng)建一個(gè)普通的目錄作為項(xiàng)目目錄。OK,可以寫(xiě)頁(yè)面了。就是寫(xiě)html js flash什么的,都可。
4.編寫(xiě)一個(gè)xml文件,名字不限。內(nèi)容嘛~~~~
看看這個(gè)文件,airSDK\templates\descriptor-template.xml 里面有詳細(xì)的解釋,拿過(guò)來(lái)改改即可,給一個(gè)例子:
<?xml version="1.0" encoding="UTF-8"?>
<application xmlns="http://ns.adobe.com/air/application/1.0.M6">
<id>examples.html.HelloWorld</id>
<version>0.1</version>
<filename>HelloWorld</filename>
<initialWindow>
<content>HelloWorld.html</content>
<visible>true</visible>
<width>400</width>
<height>200</height>
</initialWindow>
</application>
5.運(yùn)行airSDK\bin\adl.exe (那個(gè)創(chuàng)建的xml文件名),運(yùn)行即可。
PS:我一般用eclipse來(lái)編輯,用外部命令的工具來(lái)運(yùn)行adl,很方便。
簡(jiǎn)單的說(shuō)了一下Air的開(kāi)發(fā)方法后,我們來(lái)簡(jiǎn)單的看一下Ext都對(duì)Air提供了什么支持。
1.Ext.air.FileProvider
Ext提供狀態(tài)保存的功能,在對(duì)AIr的支持中Ext實(shí)現(xiàn)了一個(gè)Provider,這個(gè)Provider把狀態(tài)保存在本地目錄的一個(gè)文件里。使用方法如下:
// Initialize the state provider
Ext.state.Manager.setProvider(new Ext.air.FileProvider({
file: 'ext.state',
// if first time running
defaultState : {
mainWindow : {
width:400,
height:200,
x:10,
y:10
}
}
}));
制定Provider為Ext.air.FileProvider即可,這個(gè)操作一般在onReady里面執(zhí)行。當(dāng)然需要你先創(chuàng)建一個(gè)ext.state文本文件,在程序根目錄下即可。這樣ext的應(yīng)用運(yùn)行時(shí),窗口等大小的調(diào)整,位置之類的調(diào)整都能保存下來(lái)了。很方便。
這里包裝的Air代碼主要是:
air.File.applicationStorageDirectory.resolvePath
air.FileStream
等
2.Ext.air.NativeWindow
Ext可以調(diào)用Air實(shí)現(xiàn)Native的窗口。使用方法如下:
var win = new Ext.air.NativeWindow({
id: 'mainWindow',
instance: window.nativeWindow,
minimizeToTray: true,
trayIcon: 'ext-air/resources/icons/extlogo16.png',
trayTip: 'Simple Tasks',
trayMenu : [{
text: 'Open Simple Tasks',
handler: function(){
win.activate();
}
}, '-', {
text: 'Exit',
handler: function(){
air.NativeApplication.nativeApplication.exit();
}
}]
});
我們可以看到,其中最吸引人的是系統(tǒng)托盤(pán)的功能,可以方便的指定系統(tǒng)托盤(pán)的各種屬性。
這里包裝的主要是:
window.runtime.flash.html.HTMLLoader.createRootWindow
air.Screen.mainScreen.visibleBounds
3.Ext.sql.Connection
這個(gè)是重頭戲,對(duì)db的支持,我們知道Air的DB是采用sqlite3來(lái)實(shí)現(xiàn)的。Ext封裝了Air的db操作,簡(jiǎn)化統(tǒng)一了一些,而且提供了Store的支持,非常強(qiáng)大:
讓我們簡(jiǎn)單看一下用法:
首先取得connection
var conn = Ext.sql.Connection.getInstance();
而后打開(kāi)db
conn.open('ext.db');//這里的文件如果不存在會(huì)自動(dòng)創(chuàng)建
創(chuàng)建Table
conn.createTable({
name: 'user',
key: 'userId',
fields: [
{name: 'userId', type:'string'},
{name: 'name', type:'string'},
{name: 'pwd', type:'string'},
{name: 'email', type:'string'}
]
});
取得一個(gè)Table
var userDao = conn.getTable('user','userId');
查詢
var users = userDao.select();//這里可以寫(xiě)條件式
添加
var newuser = {
userId : 'sshw',
name : 'sshwsfc',
pwd : 'test',
email : 'sshwsfc@gmail.com'
}
userDao.insert(newuser);
感覺(jué)使用上還是蠻不錯(cuò)的,大家可以一點(diǎn)點(diǎn)試試看。
值得一提的是,在源碼中發(fā)現(xiàn)Connection這里設(shè)計(jì)成了工廠的模式,Connection是一個(gè)偽接口,實(shí)現(xiàn)除了Air的還有GoogleGear的,會(huì)根據(jù)所處環(huán)境選擇,灰常的好。
功能還在研究中,有心得了一點(diǎn)點(diǎn)給大家分享,
PS:打算搞一個(gè)iphone的信息管理軟件練練手。反正都是sqlite的
在朋友和同事的極力推薦下最近開(kāi)始看上了python,其實(shí)主要是還是因?yàn)閜ython是2007年度語(yǔ)言,怎么的也要與時(shí)俱進(jìn)呀.最近一路看來(lái)有些心得,希望能與大家分享,小弟其實(shí)也只接觸不到一周的python,有說(shuō)錯(cuò)的地方還望大家指出改正.
不打算從py的語(yǔ)法基礎(chǔ)說(shuō)起了,直接說(shuō)說(shuō)對(duì)django的心得:
接觸django首先需要了解可能就是他那個(gè)model,建立一個(gè)model就什么都有了,這對(duì)于搞java得人員來(lái)說(shuō)還是挺有吸引力的(當(dāng)然貌似對(duì)于動(dòng)態(tài)語(yǔ)言這都是小兒科),那么讓我們先看一個(gè)model的例子:
偷懶了,直接拿django-admin里面的User出來(lái)了
class User(models.Model):
username = models.CharField(_('username'), maxlength=30, unique=True, validator_list=[validators.isAlphaNumeric]))
first_name = models.CharField(_('first name'), maxlength=30, blank=True)
last_name = models.CharField(_('last name'), maxlength=30, blank=True)
email = models.EmailField(_('e-mail address'), blank=True)
password = models.CharField(_('password'), maxlength=128))
class Meta:
ordering = ('username',)
每個(gè)屬性就是一個(gè)庫(kù)表的字段,定義起來(lái)非常簡(jiǎn)單明了,models里面提供了很多種類的Field類似上面的EmailField。不同的Field有不同的設(shè)置,可以看相應(yīng)的原來(lái)來(lái)了解相關(guān)的設(shè)置.
在model class內(nèi)部還有一個(gè)class Meta,這個(gè)Class的屬性制定了這個(gè)表的一些存取策略,例如這里的ordering。MetaClass里面的屬性可以用model的_meta屬性取得。OK,那么這樣一個(gè)model怎么就能實(shí)現(xiàn)對(duì)數(shù)據(jù)庫(kù)表的靈活操作了呢。讓我們來(lái)看看吧。
首先先分析一下/django/django/db/models/base.py這個(gè)文件,其中包含了models.Model這類的定義:
看看class定義的第一行吧,第一行就夠我琢磨一陣子的了:
class Model(object):
__metaclass__ = ModelBase
Model采用了new style class定義,關(guān)于這個(gè)內(nèi)容大家可以放狗看一下,第一行是一個(gè)__metaclass__屬性的定義,該屬性的值是ModelBase,這是一個(gè)類。__metaclass__的意思是,指定一個(gè)class,這個(gè)class的實(shí)例就是本class,相信您已經(jīng)暈了。那么就拿這個(gè)Model的例子來(lái)說(shuō)明一下,如果沒(méi)有__metaclass__這個(gè)屬性,產(chǎn)生一個(gè)實(shí)例就是正常的流程,有了這個(gè)屬性流程會(huì)有改變:
首先調(diào)用BaseModel.__new__(cls, name, bases, attrs)這個(gè)方法,回返回的值是一個(gè)class類型,然后用這個(gè)class來(lái)創(chuàng)建實(shí)例。其實(shí)BaseModel就是Model的元類,來(lái)制定Model這個(gè)類的最終樣子。關(guān)于元類的更多信息請(qǐng)看這里
那么我們的目光一下轉(zhuǎn)移到BaseModel這個(gè)類上,我有種直覺(jué),Meta這個(gè)class最后可以用_meta來(lái)取就是在這里做的手腳,看一下BaseModel的定義吧,有點(diǎn)長(zhǎng):
class ModelBase(type):
"Metaclass for all models"
def __new__(cls, name, bases, attrs):
# If this isn't a subclass of Model, don't do anything special.
if name == 'Model' or not filter(lambda b: issubclass(b, Model), bases): #1
return super(ModelBase, cls).__new__(cls, name, bases, attrs)
# Create the class.
new_class = type.__new__(cls, name, bases, {'__module__': attrs.pop('__module__')}) #2
new_class.add_to_class('_meta', Options(attrs.pop('Meta', None))) #3
new_class.add_to_class('DoesNotExist', types.ClassType('DoesNotExist', (ObjectDoesNotExist,), {}))
# Build complete list of parents #4
for base in bases:
# TODO: Checking for the presence of '_meta' is hackish.
if '_meta' in dir(base):
new_class._meta.parents.append(base)
new_class._meta.parents.extend(base._meta.parents)
model_module = sys.modules[new_class.__module__]
if getattr(new_class._meta, 'app_label', None) is None:
# Figure out the app_label by looking one level up.
# For 'django.contrib.sites.models', this would be 'sites'.
new_class._meta.app_label = model_module.__name__.split('.')[-2] #5
# Bail out early if we have already created this class.
m = get_model(new_class._meta.app_label, name, False) #6
if m is not None:
return m
# Add all attributes to the class.
for obj_name, obj in attrs.items():
new_class.add_to_class(obj_name, obj) #7
# Add Fields inherited from parents
for parent in new_class._meta.parents:
for field in parent._meta.fields:
# Only add parent fields if they aren't defined for this class.
try:
new_class._meta.get_field(field.name)
except FieldDoesNotExist:
field.contribute_to_class(new_class, field.name) #8
new_class._prepare()
register_models(new_class._meta.app_label, new_class) #9
# Because of the way imports happen (recursively), we may or may not be
# the first class for this model to register with the framework. There
# should only be one class for each model, so we must always return the
# registered version.
return get_model(new_class._meta.app_label, name, False) #10
簡(jiǎn)單分析一下這個(gè)代碼:
1. 檢查class是否為Model的子類,不是的話,不做任何處理,直接傳給父類處理,也就相當(dāng)于正常的處理了class,注意super在多重繼承的時(shí)候應(yīng)該嚴(yán)格使用
2. 用type來(lái)創(chuàng)建類,創(chuàng)建的就是正常的ModelClass
3. 這句很重要,add_to_class是Model里面的class方法,這個(gè)方法其實(shí)就是傳入name和value,給Model添加class屬性.看到了,原來(lái)神奇的_meta就是這么來(lái)的. 提到add_to_class方法,簡(jiǎn)單看一下它的代碼:
def add_to_class(cls, name, value):
if name == 'Admin':
assert type(value) == types.ClassType, "%r attribute of %s model must be a class, not a %s object" % (name, cls.__name__, type(value))
value = AdminOptions(**dict([(k, v) for k, v in value.__dict__.items() if not k.startswith('_')]))
if hasattr(value, 'contribute_to_class'):
value.contribute_to_class(cls, name)
else:
setattr(cls, name, value)
add_to_class = classmethod(add_to_class)
最后一句是制定這個(gè)方法是class方法,特點(diǎn)就是方法的第一個(gè)參數(shù)是本class,其實(shí)classmethod就是一個(gè)裝飾器,在2。4之后可以使用@來(lái)簡(jiǎn)寫(xiě)。這里不得不提的是他對(duì)Admin的特殊處理,雖然AdminOption不是在admin模塊里面的,但是這么做還是跟一個(gè)Admin的東東綁定起來(lái)了,在java的世界解耦是一件大事,看到下面還有對(duì)'contribute_to_class'這個(gè)方法的特殊處理,django為啥不弄的解耦點(diǎn)呢。而且同樣是包裝成Option,一個(gè)是在BaseModel里面弄(那個(gè)Meta的包裝),一個(gè)在add_to_class方法里面弄,實(shí)在有點(diǎn)不優(yōu)雅,可能還沒(méi)了解太多,不知道他的深度用意吧。
4. Meta的集成,Option的這個(gè)類提供繼承方法
5. 取得applabel,就是把model的名字分割取到數(shù)第二個(gè),我很喜歡-2這樣的設(shè)定
6. get_model方法取得緩存里面的東西。
7. 把所有的class attr拿出來(lái)搞一遍,一般的屬性就setattr弄回去了,要是這個(gè)屬性有contribute_to_class這個(gè)callable屬性,那就執(zhí)行之(Admin的處理完全也可以這樣,其實(shí)我們常用的objects就是用這個(gè)方法弄的)
8. 每個(gè)Field調(diào)用自己的contribute_to_class方法來(lái)進(jìn)行特殊的處理
9. 進(jìn)入緩存,,暫且叫緩存吧,里面的東西大家看看很簡(jiǎn)單 文件在 /django/django/db/models/loading.py 里面還是有很多內(nèi)容的
10.看注釋說(shuō)的很清楚了,我們一定要在緩存里面拿model。
其中需要指出的是,new_class._prepare() 這個(gè)方法,簡(jiǎn)單列出片段:
def _prepare(cls):
# Creates some methods once self._meta has been populated.
opts = cls._meta
opts._prepare(cls)
....
dispatcher.send(signal=signals.class_prepared, sender=cls)
中間省略了一些代碼,不是我沒(méi)看懂的就是沒(méi)意思的,關(guān)鍵要看這個(gè)dispatcher呀。這里是監(jiān)聽(tīng)者模式,dispatcher.send(signal=signals.class_prepared, sender=cls)放松了一個(gè)包含特定信號(hào)的事件,讓監(jiān)聽(tīng)的人可以做相應(yīng)的處理。這樣的信號(hào)還有很多種,我們可以很簡(jiǎn)單的截獲信號(hào),處理相應(yīng)的內(nèi)容。也許您還記得,在我們創(chuàng)建db的時(shí)候,會(huì)提示創(chuàng)建一個(gè)超級(jí)用戶,其實(shí)就是用這個(gè)方法來(lái)弄的。
那我為什么要把這個(gè)單獨(dú)拿出來(lái)說(shuō)呢,因?yàn)楸O(jiān)聽(tīng)這個(gè)事件的人不是別人,是"objects"!!!在文件/django/django/db/models/manager.py的開(kāi)頭就有這樣的代碼:
def ensure_default_manager(sender):
cls = sender
if not hasattr(cls, '_default_manager'):
# Create the default manager, if needed.
try:
cls._meta.get_field('objects')
raise ValueError, "Model %s must specify a custom Manager, because it has a field named 'objects'" % cls.__name__
except FieldDoesNotExist:
pass
cls.add_to_class('objects', Manager())
dispatcher.connect(ensure_default_manager, signal=signals.class_prepared)
定義了一個(gè)callable,然后監(jiān)聽(tīng)signals.class_prepared信號(hào),呵呵,連上了吧,只要Class準(zhǔn)備好了,就調(diào)用這個(gè)方法。簡(jiǎn)單判斷有沒(méi)有_default_manager'屬性和meta里面的objects后,開(kāi)始插入objects。cls.add_to_class('objects', Manager()) 很熟悉吧,前面講過(guò)不多說(shuō)了。
PS:寫(xiě)到這里不由得感嘆,為啥同樣是往Class里面加入東東,要搞這么多的花樣呢,我以前也寫(xiě)過(guò)一個(gè)Rails配置加載過(guò)程的分析文檔,雖然一個(gè)簡(jiǎn)單的加載配置就把所有動(dòng)態(tài)語(yǔ)言玩?zhèn)€遍,但是這也太不規(guī)范了吧,可能不這么玩就不算“動(dòng)態(tài)”語(yǔ)言了吧,哈哈。
終于Model的Class造好了,相信大家以后造自己的Class也能玩出更多的花樣。那么可以開(kāi)始下一步了。我到老家后再寫(xiě)吧,打算講講神奇的objects,也就是Manager,其實(shí)就是玩QuerySet。。那里有很多的__xxx__方法,很好很強(qiáng)大