前些天去参加了Google的开发日活动,由于之后直接就去郊区所以一直没有时间写blog来谈谈感想。首先是google的OpenSocial,进入大厅签到之后转角过去就是个大网站的展台,每个柱子的一面是一个网站,都是OpenSocial的合作网站,有聚友,天际,天涯等。有幸跟聚友的CTO谭晓生先生和天际网的CTO郭应寿先生聊了聊OpenSocial使用中的益处和遇到的问题,感觉OpenSocial目前还是不太成熟,对比FB来说还有一定的差距,比如没有照片处理等等问题。而且我始终有一种感觉,OpenSocial是一个google的标准,但是各大网站在使用OpenSocial的时候几乎都会加上自己的扩展,这样下去,最终OpenSocial统一平台的目标很难实现,因为两个网站的Gidget几乎不能通用,这些问题OpenSocial的合作网站跟Google也在讨论中。另外得到的消息是,OpenSocial可能也会考虑出一套XXml,规范化OpenSocial的使用,并借此加强安全性。
稍后的OpenSocial专题topic中了解到了更多有关OpenSocial的信息,主要是Shindig了, 前一天还在跟白衣提议用ss做一个类似Shindig的东西,主要是做一个OpenSocial的实现,当时就想这玩意估计有了,但是没想到是host到apache了,在apache的孵化器中大家可以自己找找。会议的时候逮住了一个google的人问了一堆问题,过后才知道原来是google中国sns的负责人。
最大的收获实在是太意外了,在中午休息的时候,走过过道到楼下吃饭,突然发现一个熟悉的身影坐在角落里一个人在玩电脑,我晕是Andy Rubin,Android的老大。居然就坐在那里,而且旁边的人没有人在意他,要知道听android topic的人可不少呀,居然每一个人认出他来的。我叫了朋友确认一下,准备上前打招呼。刚上去打了个招呼,握了个手,又来了一个人,他一下认出Andy,并且跟Andy简短的交谈了一下。我提议先照个相,照相后简短聊下那个人就走了。过后Andy说那个人就是Google中国负责android的老大邸烁博士,我狂晕呀两位老大都让我给碰上了。稍候跟Andy聊了一下Android的发展,随后他掏出一个android的原型机,就是google IO大会上的那种机器。这里要说明的是,不管在模拟器上android的表现如何,在真机上你的体验绝对绝对是不一样的,太COOL了。尤其是第二屏的widget效果,还有那个street view效果,真机拿在手上体验就是不一样呀~~~~ 随后又了解到了一些android目前的发展情况,这里可以告诉大家的是,android是绝对值得期待的~!!!
posted @
2008-06-15 13:03 差沙 阅读(2782) |
评论 (4) |
编辑 收藏
经过两天的努力,终于在Android上面跑起来MSN了。现在实现了基本的聊天功能,打算陆续的把其他功能完善,万事开头难,相信以后的工作会很顺利。
Gtalk的功能由于有官方支持,早就弄了跟这个差不多的版本。
另外,这个软件目前是以插件的形式开发,多一个协议就是多一个apk,实现一些intent即可。官方的IM包里面有很多支持,可惜文档没有提及。
Android中文论坛原帖
posted @
2008-03-21 01:59 差沙 阅读(4194) |
评论 (2) |
编辑 收藏
今天看到Air1.0和Ext2.0.2的发布消息,很是兴奋,要知道Ext的每个版本升级都是很实惠的。
Ext2.0.2的这次升级主要是针对Air的支持,看来他们的关系是越来越近了,我也借机小试了一下Air。
简单说说Air的开发过程:
1.先要下载jre 和 airSDK
2.jre就不说了,airSDK也是简单的解压一下便可。
可以看看SDK下面的bin目录,一共俩文件,一个adl一个adt,adl是用来测试的,adt使用编辑发布的(ADT怎么让我想起来android了)
3.创建一个普通的目录作为项目目录。OK,可以写页面了。就是写html js flash什么的,都可。
4.编写一个xml文件,名字不限。内容嘛~~~~
看看这个文件,airSDK\templates\descriptor-template.xml 里面有详细的解释,拿过来改改即可,给一个例子:
<?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.运行airSDK\bin\adl.exe (那个创建的xml文件名),运行即可。
PS:我一般用eclipse来编辑,用外部命令的工具来运行adl,很方便。
简单的说了一下Air的开发方法后,我们来简单的看一下Ext都对Air提供了什么支持。
1.Ext.air.FileProvider
Ext提供状态保存的功能,在对AIr的支持中Ext实现了一个Provider,这个Provider把状态保存在本地目录的一个文件里。使用方法如下:
// 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即可,这个操作一般在onReady里面执行。当然需要你先创建一个ext.state文本文件,在程序根目录下即可。这样ext的应用运行时,窗口等大小的调整,位置之类的调整都能保存下来了。很方便。
这里包装的Air代码主要是:
air.File.applicationStorageDirectory.resolvePath
air.FileStream
等
2.Ext.air.NativeWindow
Ext可以调用Air实现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();
}
}]
});
我们可以看到,其中最吸引人的是系统托盘的功能,可以方便的指定系统托盘的各种属性。
这里包装的主要是:
window.runtime.flash.html.HTMLLoader.createRootWindow
air.Screen.mainScreen.visibleBounds
3.Ext.sql.Connection
这个是重头戏,对db的支持,我们知道Air的DB是采用sqlite3来实现的。Ext封装了Air的db操作,简化统一了一些,而且提供了Store的支持,非常强大:
让我们简单看一下用法:
首先取得connection
var conn = Ext.sql.Connection.getInstance();
而后打开db
conn.open('ext.db');//这里的文件如果不存在会自动创建
创建Table
conn.createTable({
name: 'user',
key: 'userId',
fields: [
{name: 'userId', type:'string'},
{name: 'name', type:'string'},
{name: 'pwd', type:'string'},
{name: 'email', type:'string'}
]
});
取得一个Table
var userDao = conn.getTable('user','userId');
查询
var users = userDao.select();//这里可以写条件式
添加
var newuser = {
userId : 'sshw',
name : 'sshwsfc',
pwd : 'test',
email : 'sshwsfc@gmail.com'
}
userDao.insert(newuser);
感觉使用上还是蛮不错的,大家可以一点点试试看。
值得一提的是,在源码中发现Connection这里设计成了工厂的模式,Connection是一个伪接口,实现除了Air的还有GoogleGear的,会根据所处环境选择,灰常的好。
功能还在研究中,有心得了一点点给大家分享,
PS:打算搞一个iphone的信息管理软件练练手。反正都是sqlite的
posted @
2008-02-26 13:49 差沙 阅读(4789) |
评论 (4) |
编辑 收藏
在朋友和同事的极力推荐下最近开始看上了python,其实主要是还是因为python是2007年度语言,怎么的也要与时俱进呀.最近一路看来有些心得,希望能与大家分享,小弟其实也只接触不到一周的python,有说错的地方还望大家指出改正.
不打算从py的语法基础说起了,直接说说对django的心得:
接触django首先需要了解可能就是他那个model,建立一个model就什么都有了,这对于搞java得人员来说还是挺有吸引力的(当然貌似对于动态语言这都是小儿科),那么让我们先看一个model的例子:
偷懒了,直接拿django-admin里面的User出来了
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',)
每个属性就是一个库表的字段,定义起来非常简单明了,models里面提供了很多种类的Field类似上面的EmailField。不同的Field有不同的设置,可以看相应的原来来了解相关的设置.
在model class内部还有一个class Meta,这个Class的属性制定了这个表的一些存取策略,例如这里的ordering。MetaClass里面的属性可以用model的_meta属性取得。OK,那么这样一个model怎么就能实现对数据库表的灵活操作了呢。让我们来看看吧。
首先先分析一下/django/django/db/models/base.py这个文件,其中包含了models.Model这类的定义:
看看class定义的第一行吧,第一行就够我琢磨一阵子的了:
class Model(object):
__metaclass__ = ModelBase
Model采用了new style class定义,关于这个内容大家可以放狗看一下,第一行是一个__metaclass__属性的定义,该属性的值是ModelBase,这是一个类。__metaclass__的意思是,指定一个class,这个class的实例就是本class,相信您已经晕了。那么就拿这个Model的例子来说明一下,如果没有__metaclass__这个属性,产生一个实例就是正常的流程,有了这个属性流程会有改变:
首先调用BaseModel.__new__(cls, name, bases, attrs)这个方法,回返回的值是一个class类型,然后用这个class来创建实例。其实BaseModel就是Model的元类,来制定Model这个类的最终样子。关于元类的更多信息请看这里
那么我们的目光一下转移到BaseModel这个类上,我有种直觉,Meta这个class最后可以用_meta来取就是在这里做的手脚,看一下BaseModel的定义吧,有点长:
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
简单分析一下这个代码:
1. 检查class是否为Model的子类,不是的话,不做任何处理,直接传给父类处理,也就相当于正常的处理了class,注意super在多重继承的时候应该严格使用
2. 用type来创建类,创建的就是正常的ModelClass
3. 这句很重要,add_to_class是Model里面的class方法,这个方法其实就是传入name和value,给Model添加class属性.看到了,原来神奇的_meta就是这么来的. 提到add_to_class方法,简单看一下它的代码:
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)
最后一句是制定这个方法是class方法,特点就是方法的第一个参数是本class,其实classmethod就是一个装饰器,在2。4之后可以使用@来简写。这里不得不提的是他对Admin的特殊处理,虽然AdminOption不是在admin模块里面的,但是这么做还是跟一个Admin的东东绑定起来了,在java的世界解耦是一件大事,看到下面还有对'contribute_to_class'这个方法的特殊处理,django为啥不弄的解耦点呢。而且同样是包装成Option,一个是在BaseModel里面弄(那个Meta的包装),一个在add_to_class方法里面弄,实在有点不优雅,可能还没了解太多,不知道他的深度用意吧。
4. Meta的集成,Option的这个类提供继承方法
5. 取得applabel,就是把model的名字分割取到数第二个,我很喜欢-2这样的设定
6. get_model方法取得缓存里面的东西。
7. 把所有的class attr拿出来搞一遍,一般的属性就setattr弄回去了,要是这个属性有contribute_to_class这个callable属性,那就执行之(Admin的处理完全也可以这样,其实我们常用的objects就是用这个方法弄的)
8. 每个Field调用自己的contribute_to_class方法来进行特殊的处理
9. 进入缓存,,暂且叫缓存吧,里面的东西大家看看很简单 文件在 /django/django/db/models/loading.py 里面还是有很多内容的
10.看注释说的很清楚了,我们一定要在缓存里面拿model。
其中需要指出的是,new_class._prepare() 这个方法,简单列出片段:
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)
中间省略了一些代码,不是我没看懂的就是没意思的,关键要看这个dispatcher呀。这里是监听者模式,dispatcher.send(signal=signals.class_prepared, sender=cls)放松了一个包含特定信号的事件,让监听的人可以做相应的处理。这样的信号还有很多种,我们可以很简单的截获信号,处理相应的内容。也许您还记得,在我们创建db的时候,会提示创建一个超级用户,其实就是用这个方法来弄的。
那我为什么要把这个单独拿出来说呢,因为监听这个事件的人不是别人,是"objects"!!!在文件/django/django/db/models/manager.py的开头就有这样的代码:
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)
定义了一个callable,然后监听signals.class_prepared信号,呵呵,连上了吧,只要Class准备好了,就调用这个方法。简单判断有没有_default_manager'属性和meta里面的objects后,开始插入objects。cls.add_to_class('objects', Manager()) 很熟悉吧,前面讲过不多说了。
PS:写到这里不由得感叹,为啥同样是往Class里面加入东东,要搞这么多的花样呢,我以前也写过一个Rails配置加载过程的分析文档,虽然一个简单的加载配置就把所有动态语言玩个遍,但是这也太不规范了吧,可能不这么玩就不算“动态”语言了吧,哈哈。
终于Model的Class造好了,相信大家以后造自己的Class也能玩出更多的花样。那么可以开始下一步了。我到老家后再写吧,打算讲讲神奇的objects,也就是Manager,其实就是玩QuerySet。。那里有很多的__xxx__方法,很好很强大
posted @
2008-02-02 17:32 差沙 阅读(3225) |
评论 (1) |
编辑 收藏
Android是google为手机开发的操作系统, 基于Linux2.6内核.
2007年11月12日(北美时间), Android的APP SDK公布, 开始了google手机的开发大赛. 我们致力于Android的开发文档翻译, 开发技术交流等工作, 希望为Android平台在中国的推广贡献自己的力量.
Andorid的SDK是完全针对java设计的, 甚至提供eclipse的插件, 作为一个javaer不研究实在可惜.
现在中文文档已经有了初步进展, 大家翻译的热情都很高涨. 论坛里的讨论也十分热烈, 欢迎您的访问.
我们的网站,
http://www.androidcn.net
中文文档计划:
http://www.androidcn.net/wiki
PS: 管理员您好, 不知道这个符不符合首页发布的规则, 要是不妥我会撤下, 我们都想为Android中文化贡献力量
posted @
2007-11-15 13:41 差沙 阅读(2323) |
评论 (0) |
编辑 收藏
为了记录自己看Rails源码的过程,全程记录无废话。
我们看看script/server都干了什么
require File.dirname(__FILE__)
+
'
/../config/boot
'
require
'
commands/server
'
引用了boot.rb这个文件。看来这个文件是rails启动的入口,来看看怎么回事吧。
unless defined?(RAILS_ROOT)
root_path = File.join(File.dirname(__FILE__), '..')
unless RUBY_PLATFORM =~ /mswin32/
require 'pathname'
root_path = Pathname.new(root_path).cleanpath(true).to_s
end
RAILS_ROOT = root_path
end 这一部分定义了RAILS_ROOT这个系统的全局变量,指定了项目的根目录,大家可以在以后华丽的使用了。
下一部分是找到rails,粗略看一下。
if File.directory?("#{RAILS_ROOT}/vendor/rails")
require "#{RAILS_ROOT}/vendor/rails/railties/lib/initializer"
else
require 'rubygems' 这里能看到,他先跑到
vendor/rails去找rails了,这就是我们为什么能在插件里用rails是原因。如果没有那么gems的干活。
接下来是初始化一下load_path,没什么看的了。boot.rb就这样的吧。
回到script/server的第二行,包含了'commands/server'这个文件,这个文件是什么?Rails的源码里面找吧。我们在Rails的源码里面找到这个文件。
require 'active_support'
require 'fileutils'
begin
require_library_or_gem 'fcgi'
rescue Exception
# FCGI not available
end
server = case ARGV.first
when "lighttpd"
ARGV.shift
when "webrick"
ARGV.shift
else
if RUBY_PLATFORM !~ /mswin/ && !silence_stderr { `lighttpd -version` }.blank? && defined?(FCGI)
"lighttpd"
else
"webrick"
end
end
if server == "webrick"
puts "=> Booting WEBrick"
else
puts "=> Booting lighttpd (use 'script/server webrick' to force WEBrick)"
end
FileUtils.mkdir_p(%w( tmp/sessions tmp/cache tmp/sockets ))
require "commands/servers/#{server}"
没想到ActiveRecord居然是在这里引用的,这个ActiveRecord里面扩展了很对Ruby的既有类型,所以我们看源码的时候如果发现有不熟悉的方法,就来这里找找,当然,看Rails的API是最好的选择。
从参数一目了然,我们可以传入server的名字,
lighttpd和webrick,根据不同的server选择不同的server文件来读取。我们还是看看webrick的吧。
require 'webrick'
require 'optparse'
OPTIONS = {
:port => 3000,
:ip => "0.0.0.0",
:environment => (ENV['RAILS_ENV'] || "development").dup,
:server_root => File.expand_path(RAILS_ROOT + "/public/"),
:server_type => WEBrick::SimpleServer,
:charset => "UTF-8",
:mime_types => WEBrick::HTTPUtils::DefaultMimeTypes
}
ARGV.options do |opts|
script_name = File.basename($0)
opts.banner = "Usage: ruby #{script_name} [options]"
opts.separator ""
opts.on("-p", "--port=port", Integer,
"Runs Rails on the specified port.",
"Default: 3000") { |v| OPTIONS[:port] = v }
opts.on("-b", "--binding=ip", String,
"Binds Rails to the specified ip.",
"Default: 0.0.0.0") { |v| OPTIONS[:ip] = v }
opts.on("-e", "--environment=name", String,
"Specifies the environment to run this server under (test/development/production).",
"Default: development") { |v| OPTIONS[:environment] = v }
opts.on("-m", "--mime-types=filename", String,
"Specifies an Apache style mime.types configuration file to be used for mime types",
"Default: none") { |mime_types_file| OPTIONS[:mime_types] = WEBrick::HTTPUtils::load_mime_types(mime_types_file) }
opts.on("-d", "--daemon",
"Make Rails run as a Daemon (only works if fork is available -- meaning on *nix)."
) { OPTIONS[:server_type] = WEBrick::Daemon }
opts.on("-c", "--charset=charset", String,
"Set default charset for output.",
"Default: UTF-8") { |v| OPTIONS[:charset] = v }
opts.separator ""
opts.on("-h", "--help",
"Show this help message.") { puts opts; exit }
opts.parse!
end
ENV["RAILS_ENV"] = OPTIONS[:environment]
RAILS_ENV.replace(OPTIONS[:environment]) if defined?(RAILS_ENV)
require RAILS_ROOT + "/config/environment"
require 'webrick_server'
OPTIONS['working_directory'] = File.expand_path(RAILS_ROOT)
puts "=> Rails application started on http://#{OPTIONS[:ip]}:#{OPTIONS[:port]}"
puts "=> Ctrl-C to shutdown server; call with --help for options" if OPTIONS[:server_type] == WEBrick::SimpleServer
DispatchServlet.dispatch(OPTIONS)
本来不想把大段的代码贴上来,但是这里面的内容可能大家都比较关心,涉及到server的启动参数。
:port
=> 端口,
:ip => server ip,
:environment =>运行环境,
:server_root => web访问的目录,(很多人问这个怎么改)
:server_type => WEBrick::SimpleServer,
:charset => "UTF-8", 编码
:mime_types => WEBrick::HTTPUtils::DefaultMimeTypes
后面的require 引入了两个文件,一个是'webrick_server',别看,就是他。另外一个是config/environment,这个文件是系统的全局配置文件,很重要,我们还是下次看看这个文件去吧。里面还真挺有意思。
(不知道blogjava让不让写ROR的文章,看到有人写了所以放在首页了,如果不妥,我会尽快删除)
posted @
2006-11-20 23:43 差沙 阅读(4562) |
评论 (0) |
编辑 收藏