<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom"><title type="text">博客园_编程点滴，目前主要研究Android</title><subtitle type="text">对待生活,应该怀着一颗感恩的心</subtitle><id>http://feed.cnblogs.com/blog/u/8829/rss</id><updated>2012-04-20T08:12:23Z</updated><author><name>chengbo</name><uri>http://www.cnblogs.com/chengbo/</uri></author><generator>feed.cnblogs.com</generator><link rel="alternate" type="text/html" href="http://www.cnblogs.com/chengbo/"/><link rel="self" type="application/atom+xml" href="http://feed.cnblogs.com/blog/u/8829/rss"/><entry><id>http://www.cnblogs.com/chengbo/archive/2012/04/20/use-gitolite-to-manage-git-repositories.html</id><title type="text">使用Gitolite来对Git的repository实现权限控制</title><summary type="text">我们项目组打算从svn向git迁移，前几天我搭建了git环境，把代码从svn转移过来，然后所有成员都通过server上的git账号来做pull和push，一切都安置妥当，没有问题。但是后来其它项目组也打算使用这个git server，那么问题来了，之前那种授权的方式肯定是不够的，因为只要能连上server，那么他对这个server上所有的repository都有完全的读写权限，这显然是不可接受的。 所以打算使用Gitolite这个组件来做权限控制，搜索了下，找到的文章貌似都是老版本的，所以有了写这篇文章的想法。 Gitolite其实也是一个git repository，首先在server上安装</summary><published>2012-04-20T08:12:00Z</published><updated>2012-04-20T08:12:00Z</updated><author><name>chengbo</name><uri>http://www.cnblogs.com/chengbo/</uri></author><link rel="alternate" href="http://www.cnblogs.com/chengbo/archive/2012/04/20/use-gitolite-to-manage-git-repositories.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/chengbo/archive/2012/04/20/use-gitolite-to-manage-git-repositories.html"/><content type="html">&lt;p&gt;我们项目组打算从svn向git迁移，前几天我搭建了git环境，把代码从svn转移过来，然后所有成员都通过server上的git账号来做pull和push，一切都安置妥当，没有问题。但是后来其它项目组也打算使用这个git server，那么问题来了，之前那种授权的方式肯定是不够的，因为只要能连上server，那么他对这个server上所有的repository都有完全的读写权限，这显然是不可接受的。 所以打算使用Gitolite这个组件来做权限控制，搜索了下，找到的文章貌似都是老版本的，所以有了写这篇文章的想法。 Gitolite其实也是一个git repository，首先在server上安装好后，在client上把server上的repository clone下来，在本地做一些更改，再push回server，server端的hooks会根据push上来的配置来更新权限。 接下来，介绍下安装和配置步骤&lt;/p&gt;&lt;p&gt;&lt;strong&gt;准备工作&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;如果你之前是用git账号来做权限控制的话，记得把&lt;code&gt;/etc/passwd&lt;/code&gt;里git用户的shell换回&lt;code&gt;/bin/bash&lt;/code&gt;，然后把&lt;code&gt;~git/.ssh/authorized_key&lt;/code&gt;里不再需要的key移除。 用&lt;code&gt;ssh-kengen&lt;/code&gt;生成一对key，比如your-name和your-name.pub（下文均以此为例） 拷贝私钥到本用户的.ssh文件夹中&lt;/p&gt;mv your-name ~/.ssh/&lt;p&gt;拷贝公钥到git server上&lt;/p&gt;scp you-name.pub git@your.server.name.or.ip.address:~&lt;p&gt;为了以后方便，这里可以做一个server别名，指定连接所需的用户名，server的地址、端口以及私钥&lt;/p&gt;vim ~/.ssh/config&lt;p&gt;输入以下内容&lt;/p&gt;host githost&lt;br/&gt;user git&lt;br/&gt;hostname your.server.name.or.ip.address&lt;br/&gt;port 22&lt;br/&gt;identityfile ~/.ssh/your-name&lt;p&gt;&lt;strong&gt;安装Gitolite&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;登录git server&lt;/p&gt;ssh git@your.server.name.or.ip.address&lt;p&gt;下载最新的Gitolite&lt;/p&gt;git clone git://github.com/sitaramc/gitolite&lt;p&gt;安装，这里说明下，安装方式有3种，区别在与指定生成&lt;code&gt;gitolite&lt;/code&gt;可执行文件的路径，这里采用Gitolite作者推荐的第二种，也就是把文件生成到&lt;code&gt;$HOME/bin&lt;/code&gt;中，这样可以在接下来的bash中直接执行&lt;code&gt;gitolite&lt;/code&gt;命令而不用指定路径(如果你的&lt;code&gt;~/bin&lt;/code&gt;目录不存在记得先&lt;code&gt;mkdir ~/bin&lt;/code&gt;)&lt;/p&gt;gitolite/install -ln&lt;p&gt;设置，由于是第一次运行这个命令，所以这里指定的key是拥有Gitolite管理员权限的&lt;/p&gt;gitolite setup -pk your-name.pub&lt;p&gt;此命令会在你的&lt;code&gt;~/repositories/&lt;/code&gt;目录生成两个repository：gitolite-admin.git和testing.git&lt;/p&gt;&lt;p&gt;&lt;strong&gt;配置权限&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;退到你的workstation上&lt;/p&gt;exit&lt;p&gt;clone刚才生成的gitolite-admin.git&lt;/p&gt;git clone githost:gitolite-admin&lt;p&gt;注意这里用的是刚才准备好的server别名来连接的，其中最重要的区别是使用your-name.pub这个key，并且没有采用绝对路径来指定想要clone的repository，而是直接使用名称，并且这个名称也没有包括.git这个后缀。这一点很重要，因为这是用Gitolite的机制来clone，如果你跳过它直接使用git来，那么它的一些功能就无法实现了。以后clone, push其它需要受Gitolite权限控制的repository都必须这样做。 clone完后会有个新的目录&lt;code&gt;gitolite-admin&lt;/code&gt;，里面有两个文件夹&lt;code&gt;conf&lt;/code&gt;和&lt;code&gt;keydir&lt;/code&gt;，第一个目录中包含的是配置文件，里面就是记录权限配置的地方，第二个目录中则包含所有用户的pub key。 现在我们打开配置文件，按照我们的权限配置需要进行设置&lt;/p&gt;vim gitolite-admin/conf/gitolite.conf&lt;p&gt;我期望的配置如下，你也可以根据你的需要做更改&lt;/p&gt;@repos_a @proj1 @proj2&lt;br/&gt;@repos_b @proj3 @proj4 @proj5&lt;br/&gt;&lt;br/&gt;@team_a @user1 @user2&lt;br/&gt;@team_b @user3 @user4&lt;br/&gt;&lt;br/&gt;repo gitolite-admin&lt;br/&gt;RW+ = your-name&lt;br/&gt;&lt;br/&gt;repo @repos_a&lt;br/&gt;RW+ = @team_a&lt;br/&gt;R = @all&lt;br/&gt;&lt;br/&gt;repo @repos_b&lt;br/&gt;RW+ = @team_b&lt;p&gt;这个配置很简单，首先定义了两个repository group，再又定义了两个user group，group的好处就是以后添加repository和user的时候，不需要再单独配置，只需加入到对应的group中即可。&lt;/p&gt;&lt;ul&gt;&lt;li&gt;添加全新的repository，在上面提到的gitolite.conf文件中配置好对应的名称和权限，再push到server即可，server会自动帮你创建一个empty的bare repository。&lt;/li&gt;&lt;li&gt;如果你已经有一个repository，想把它加进来的话，那就把它拷贝到git server上的&lt;code&gt;~/repositories&lt;/code&gt;文件夹里，记得文件夹名要以.git结尾，并且这个repository一定要是bare的，（你可以通过拷贝repository里的.git文件夹，然后运行&lt;code&gt;git config --bool core.bare true&lt;/code&gt;，也可以运行&lt;code&gt;git clone --bare your-repository&lt;/code&gt;来得到bare repository）。这种方式还有一个额外的操作就是在server上运行一次&lt;code&gt;gitolite setup&lt;/code&gt;。&lt;/li&gt;&lt;li&gt;移除repository，在配置文件中移除对应的repo，然后push，接着再删除server上对应的文件夹即可。&lt;/li&gt;&lt;/ul&gt;&lt;ul&gt;&lt;li&gt;添加user，把pub key拷贝到&lt;code&gt;keydir&lt;/code&gt;文件夹里&lt;/li&gt;&lt;li&gt;删除user，一样，移除&lt;code&gt;keydir&lt;/code&gt;里对应的pub key&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;注意，上面说的操作，都必须在clone的gitolite-admin里做更改，然后push，千万别在server上自己来，那样是没用的，因为这些权限配置、repository管理都有一些额外的操作，gitolite-admin会帮你搞定一切。 把你的更改push回server上，试试clone，pull，push，看看权限是否正确。比如&lt;/p&gt;git clone githost:proj3&lt;p&gt;更多的内容，可以参考&lt;a href="http://sitaramc.github.com/gitolite/master-toc.html"&gt;官方文档&lt;/a&gt; 本文由Roy最初发表于：&lt;a href="http://blog.chengbo.net/2012/04/20/use-gitolite-to-manage-git-repositories.html"&gt;http://blog.chengbo.net/2012/04/20/use-gitolite-to-manage-git-repositories.html&lt;/a&gt;，你可以在保持文章完整和保留本声明的情况下转帖、分发和印刷等。&lt;/p&gt;&lt;img src="http://www.cnblogs.com/chengbo/aggbug/2459474.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/chengbo/archive/2012/04/20/use-gitolite-to-manage-git-repositories.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/chengbo/archive/2012/04/20/use-debian-server-as-a-router.html</id><title type="text">用Debian当路由，来解决BT造成的网络慢的问题</title><summary type="text">自从@TimothyYe童鞋介绍偶加入HDC后，为了快点完成新人作业，也为了满足我不折腾不舒服斯基的欲望，哥配了一台凌动小PC，Intel ATOM D525NW的主板，集成了CPU和显卡，加上小机箱总共700元。到手后，插上我Thinkpad拆下来的2根1G内存和另外一台闲置N久的台式机160G SATA硬盘，装了个Debian，就可以用了。 装上transmission后，全速挂BT无压力，比那些直接路由或者1、200的NAS给力多了。哥还继续在上面折腾了Git，emule，动态DNS等，远远没有把2G内存榨干，当然这里都说远了，继续回来。 我家使用的是电信ADSL，一个宽带无线路由，手机</summary><published>2012-04-20T08:11:00Z</published><updated>2012-04-20T08:11:00Z</updated><author><name>chengbo</name><uri>http://www.cnblogs.com/chengbo/</uri></author><link rel="alternate" href="http://www.cnblogs.com/chengbo/archive/2012/04/20/use-debian-server-as-a-router.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/chengbo/archive/2012/04/20/use-debian-server-as-a-router.html"/><content type="html">&lt;p&gt;自从&lt;a title="timothy ye" href="http://www.weibo.com/timothyye" target="_blank"&gt;@TimothyYe&lt;/a&gt;童鞋介绍偶加入HDC后，为了快点完成新人作业，也为了满足我不折腾不舒服斯基的欲望，哥配了一台凌动小PC，Intel ATOM D525NW的主板，集成了CPU和显卡，加上小机箱总共700元。到手后，插上我Thinkpad拆下来的2根1G内存和另外一台闲置N久的台式机160G SATA硬盘，装了个Debian，就可以用了。 装上transmission后，全速挂BT无压力，比那些直接路由或者1、200的NAS给力多了。哥还继续在上面折腾了Git，emule，动态DNS等，远远没有把2G内存榨干，当然这里都说远了，继续回来。 我家使用的是电信ADSL，一个宽带无线路由，手机，notebook，iPad，PC，xbox等（哥真败家。。。），路由拨号连入Internet，然后通过WIFI把其它设备连入LAN，共享外网连接。这个配置在我挂PT之前一直工作正常，可是当我把BT开着，就算上传和下载速度都为0，LAN中的其它设备访问Internet的速度一样很慢，很慢。 分析了下，估计是我那100元的低端无线路由无法支撑如此多的连接会话造成的，简单直接的办法就是升级路由，于是开始上网查高端路由，不查不知道，一查才知道这东西好贵，便宜的怕是不能解决问题，贵的哥又承受不了。纠结了N久，最后发现，何不把我那台Debian来做路由呢？ 马上在淘宝买了根20元的USB有线网卡，收到后插入Debian上，这东西不像Windows和MAC可以自动识别出来然后提示你安装驱动，要自己去折腾，而且附送的光盘上也没有Linux的驱动，看来，要找Google了。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;安装配置USB网卡&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;在Debian上运行&lt;/p&gt;chengbo@chengbo-server:~$ lsusb&lt;p&gt;Bus 005 Device 002: ID 0fe6:9700 Kontron (Industrial Computer Source / ICS Advent) DM9601 Fast Ethernet Adapter 从上得知，USB网卡是DM9601这个型号的&lt;/p&gt;chengbo@chengbo-server:~$ /sbin/ifconfig&lt;p&gt;只有lo和eth0，新加的网卡没有识别 以DM9601为关键字，Google，找到了&lt;a href="http://www.davicom.com.tw/page1.aspx?no=209814"&gt;这里&lt;/a&gt;，下载解压好linux的驱动后，编译出错，好像是头文件不对，哥不会写驱动啊，只有继续Google，发现DM9601的驱动已经集成在新版的内核里了，但是我试了下，用不了，不知道什么原因。继续Google，又找到了&lt;a href="http://ceyes.blog.51cto.com/2377614/808386"&gt;这里&lt;/a&gt;，根据上面的说明，下载了qf9700的驱动，编译，成功，生成文件qf9700.ko。 安装刚才编译好的驱动&lt;/p&gt;root@chengbo-server:~$ cp qf9700.ko /lib/modules/`uname -r`/kernel/drivers/net/usb&lt;br/&gt;root@chengbo-server:~$ cd /lib/modules/`uname -r`/kernel/drivers/net/usb&lt;br/&gt;root@chengbo-server: usb$ modprobe usbnet&lt;br/&gt;root@chengbo-server: usb$ insmod qf9700.ko&lt;br/&gt;root@chengbo-server: usb$ ifconfig eth1 up&lt;p&gt;配置好驱动后再运行&lt;/p&gt;root@chengbo-server:~$ ifconfig&lt;p&gt;多了一个eth1了，到现在新网卡已经可以使用了。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;安装配置ADSL拨号相关软件&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;把原先连接无线宽带路由和猫的网线拔掉，接在猫和Debian的USB网卡上 安装拨号软件&lt;/p&gt;root@chengbo-server:~$ apt-get install pppoe pppoeconf&lt;p&gt;成功后运行&lt;/p&gt;root@chengbo-server:~$ pppoeconf&lt;p&gt;会弹出一个窗口，自动检测连接ADSL的网卡，然后照提示输入你的用户名，密码，其它的可以用默认值。 运行&lt;/p&gt;root@chengbo-server:~$ pon dsl-provider&lt;p&gt;就可以拨号了，过后再&lt;code&gt;ifconfig&lt;/code&gt;一下，会发现多了个ppp0。&lt;code&gt;poff&lt;/code&gt;命令可以关闭ppp0连接。&lt;em&gt;另外，我发现多次拨号可以有多个ppp，比如ppp1，而且IP还不一样，不知道这样是否可以让带宽double，待测试。&lt;/em&gt;此时Debian可以上网了，但是LAN中的其它设备还不行。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;设置LAN路由&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;设置Debian连接LAN的网卡配置&lt;/p&gt;root@chengbo-server:~$ vim /etc/network/interfaces&lt;blockquote style='border:2px solid #EFEFEF;color:#333333;padding:5px 10px;'&gt;allow-hotplug eth0 iface eth0 inet static address 192.168.3.3 netmask 255.255.255.0 network 192.168.3.0 broadcast 192.168.3.255 gateway 192.168.3.3&lt;/blockquote&gt;&lt;p&gt;由于所有的无线设备都是有无线宽带路由来DHCP的，所以登录无线宽带路由，把配置改下：&lt;/p&gt;&lt;blockquote style='border:2px solid #EFEFEF;color:#333333;padding:5px 10px;'&gt;range 192.168.3.100-192.168.3.200 netmask 255.255.255.0 gateway 192.168.3.3 dns 8.8.8.8 or 4.4.4.4&lt;/blockquote&gt;&lt;p&gt;DNS没有用电信分配给我的，是因为不想看电信强行插入的广告 设置NAT&lt;/p&gt;root@chengbo-server:~$ echo "1" &amp;gt; /proc/sys/net/ipv4/ip_forward&lt;br/&gt;root@chengbo-server:~$ /sbin/iptables -t nat -A POSTROUTING -o ppp0 -s 192.168.3.0/24 -j MASQUERADE&lt;p&gt;至此LAN中的其它设备也可以上网了，如果还不行的话，检查下你的配置是否正确，然后再看看路由表，把错误的路由改掉。 最后，我家网络的结构如下图 &lt;a href="http://blog.chengbo.net/wp-content/uploads/2012/04/home-network.png"&gt;&lt;img class="alignnone size-medium wp-image-372" title="home network" src="http://blog.chengbo.net/wp-content/uploads/2012/04/home-network-300x192.png" alt="home network" /&gt;&lt;/a&gt; &lt;span style="color: #008000;"&gt;// TODO: 此文还需添加Debian重启后自动配置USB网卡，拨号，NAT的内容&lt;/span&gt; 本文由Roy最初发表于：&lt;a href="http://blog.chengbo.net/2012/04/18/use-debian-server-as-a-router.html"&gt;http://blog.chengbo.net/2012/04/18/use-debian-server-as-a-router.html&lt;/a&gt;，你可以在保持文章完整和保留本声明的情况下转帖、分发和印刷等。&lt;/p&gt;&lt;img src="http://www.cnblogs.com/chengbo/aggbug/2459471.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/chengbo/archive/2012/04/20/use-debian-server-as-a-router.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/chengbo/archive/2012/04/10/faster-emulator-with-better-hardware.html</id><title type="text">更快的，更好的支持硬件的模拟器</title><summary type="text">原文：http://android-developers.blogspot.com/2012/04/faster-emulator-with-better-hardware.html [This post is by Xavier Ducrohet and Reto Meier of the Android engineering team. — Tim Bray.]Android模拟器是开发和测试Android程序的一个关键工具。目前Android设备的功能以及多样性发展的日益迅猛，模拟器要跟上步伐十分的困难。 今天我们激动的宣布，模拟器做了一些十分显著的改进，包括激动人心的性能提升，众多硬</summary><published>2012-04-10T15:19:00Z</published><updated>2012-04-10T15:19:00Z</updated><author><name>chengbo</name><uri>http://www.cnblogs.com/chengbo/</uri></author><link rel="alternate" href="http://www.cnblogs.com/chengbo/archive/2012/04/10/faster-emulator-with-better-hardware.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/chengbo/archive/2012/04/10/faster-emulator-with-better-hardware.html"/><content type="html">&lt;p&gt;原文：&lt;a href="http://android-developers.blogspot.com/2012/04/faster-emulator-with-better-hardware.html"&gt;http://android-developers.blogspot.com/2012/04/faster-emulator-with-better-hardware.html&lt;/a&gt; &lt;em&gt;[This post is by Xavier Ducrohet and Reto Meier of the Android engineering team. &amp;mdash; Tim Bray.]&lt;/em&gt;Android模拟器是开发和测试Android程序的一个关键工具。目前Android设备的功能以及多样性发展的日益迅猛，模拟器要跟上步伐十分的困难。 今天我们激动的宣布，模拟器做了一些十分显著的改进，包括激动人心的性能提升，众多硬件特性，尤其是传感器和多点触控的支持。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;加入GPU支持&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;今天我们发布的系统镜像内置了GPU支持（Android 4.0.3 r2）。Android日益依赖GPU来提高性能，所以新模拟器的差异十分显著。在下面的视频中（需翻墙才能看）模拟器依旧翻译着ARM指令（运行模拟器的宿主系统一般是x86平台，此镜像是ARM平台的，所以中间存在着ARM-&amp;gt;x86指令的转换。之前没有GPU支持，运行如此高分辨率的模拟器并不流畅）；GPU可以让性能提升不少。 &lt;iframe src="http://www.youtube.com/embed/T--vFtyZvc4" frameborder="0" width="420" height="315"&gt;&lt;/iframe&gt; 一个额外的红利，我们现在已经支持OpenGL ES 2.0了，所以你的OpenGL游戏可以在模拟器中运行了。 请注意的是，目前有很多种的GPU，我们并没有用所有GPU对这个beta版的模拟器做测试，所以，如果你有什么意见或者遇到了什么问题，请&lt;a href="http://code.google.com/p/android/issues/entry?template=Tools%20GPU%20bug%20report"&gt;联系我们&lt;/a&gt;。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;模拟更多的硬件特性&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;移动设备的硬件特性是一个开发平台的重要组成部分，所以我们也高兴的宣布，除了去年加入的摄像头支持，现在还可以使用一个绑定的Android设备来支持传感器和多点触控了。 我们还在为模拟器支持更多的硬件特性，包括蓝牙和NFC（近距离无线通信），而努力。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;优化的CPU性能&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;我们同样也优化了Android模拟器的CPU性能。硬件浮点运算操作在冰淇淋三明治版本(Android 4.0)之上的版本中有效，它让模拟CPU操作大概快了2倍。 上一周，我们发布了包括x86系统镜像和主机驱动程序的Android开发工具r17版本，可以让模拟器使用x86指令执行，大大提高了执行效率。 下面这个视频显示了两个CPU相关的程序，一个有虚化（virtualization），一个没有，在两个运行着相同系统镜像的模拟器上运行的情况。（同样需要翻墙） &lt;iframe src="http://www.youtube.com/embed/1gnQX_izOrk" frameborder="0" width="420" height="315"&gt;&lt;/iframe&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;构建一个现代化的模拟器&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;因为Android平台允许应用程序和系统组件之间的深层相互操作，所以我们必须提供一个有着完整系统镜像的模拟器。我们的模拟器虚拟了一个完整的设备：硬件，内核，底层系统库和应用框架。 当然，系统一般被虚拟为ARM CPU的设备；之前，我们用软件来虚拟这些指令，它一直工作的不错，直到包括更多动画和更加复杂的Android 3.0的到来。 我们缺少的是Android x86的支持，和上周r17版本的SDK工具中的GPU支持。把模拟器的OpenGL ES 2.0指令传给宿主操作系统，转换成标准的OpenGL 2.0，然后用宿主GPU来执行，这样模拟器就支持GPU了。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;总结&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;Android生态系统有着很多的来自不同厂商的设备。开发人员需要一个不用买设备就可以测试程序的途径。同时一个快速的，更真实的模拟器有着极大的帮助。 我们希望这些新的优化能够让模拟器在你的开发和测试过程中更加有用，同时期盼能进一步的为你优化它。 本文由Roy最初发表于：&lt;a href="http://blog.chengbo.net/2012/04/10/faster-emulator-with-better-hardware.html"&gt;http://blog.chengbo.net/2012/04/10/faster-emulator-with-better-hardware.html&lt;/a&gt;，你可以在保持文章完整和保留本声明的情况下转帖、分发和印刷等。&lt;/p&gt;&lt;img src="http://www.cnblogs.com/chengbo/aggbug/2441519.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/chengbo/archive/2012/04/10/faster-emulator-with-better-hardware.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/chengbo/archive/2012/03/09/onitemclick-return-wrong-position-when-listview-has-headerview.html</id><title type="text">当LISTVIEW有HEADER时，ONITEMCLICK里的POSITION不正确</title><summary type="text">今天在做项目的时候，遇到一个问题，记录下来。当我们给ListView添加一个HeaderView后（代码如下），发现onItemClick方法里的position参数的值不是我们所期望的，比如点击ListView的第一行，我们期望的position是0，可是却是1，也就是说，它是从Header开始计数的。@Overrideprotected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.home); mAdapte...</summary><published>2012-03-09T11:51:00Z</published><updated>2012-03-09T11:51:00Z</updated><author><name>chengbo</name><uri>http://www.cnblogs.com/chengbo/</uri></author><link rel="alternate" href="http://www.cnblogs.com/chengbo/archive/2012/03/09/onitemclick-return-wrong-position-when-listview-has-headerview.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/chengbo/archive/2012/03/09/onitemclick-return-wrong-position-when-listview-has-headerview.html"/><content type="html">&lt;p&gt;今天在做项目的时候，遇到一个问题，记录下来。&lt;/p&gt;&lt;p&gt;当我们给&lt;a href="http://developer.android.com/reference/android/widget/ListView.html" target="_blank"&gt;ListView&lt;/a&gt;添加一个HeaderView后（代码如下），发现&lt;a href="http://developer.android.com/reference/android/widget/AdapterView.OnItemClickListener.html#onItemClick(android.widget.AdapterView&amp;lt;?&amp;gt;, android.view.View, int, long)" target="_blank"&gt;onItemClick&lt;/a&gt;方法里的position参数的值不是我们所期望的，比如点击ListView的第一行，我们期望的position是0，可是却是1，也就是说，它是从Header开始计数的。&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;@Override&lt;br /&gt;&lt;span style="color: #0000ff;"&gt;protected&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;void&lt;/span&gt; onCreate(Bundle savedInstanceState) {&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;super&lt;/span&gt;.onCreate(savedInstanceState);&lt;br /&gt; &lt;br /&gt;    setContentView(R.layout.home);&lt;br /&gt; &lt;br /&gt;    mAdapter = &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; MyAdapter(&lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;);&lt;br /&gt; &lt;br /&gt;    mListView = (ListView) findViewById(R.id.list);&lt;br /&gt;    mListView.addHeaderView(getLayoutInflater().inflate(R.layout.list_header));&lt;br /&gt;    mListView.setAdapter(mAdapter);&lt;br /&gt;    mListView.setOnClickListener(&lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;);&lt;br /&gt;}&lt;br /&gt; &lt;br /&gt;@Override&lt;br /&gt;&lt;span style="color: #0000ff;"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;void&lt;/span&gt; onItemClick(AdapterView&amp;lt;?&amp;gt; parent, View v, &lt;span style="color: #0000ff;"&gt;int&lt;/span&gt; position, &lt;span style="color: #0000ff;"&gt;long&lt;/span&gt; id) {&lt;br /&gt;    doSomething(mAdapter.getItem(position));&lt;br /&gt;}&lt;/div&gt;&lt;p&gt;&lt;span&gt;Google了下，发现有个老外issue过一个&lt;/span&gt;&lt;a href="http://code.google.com/p/android/issues/detail?id=4197" target="_blank"&gt;bug&lt;/a&gt;&lt;span&gt;，和我遇到的问题一样，不过这个bug被RomainGuy reject掉了，理由是，你用错了，请用&lt;/span&gt;&lt;a href="http://developer.android.com/reference/android/widget/ListView.html#getAdapter()" target="_blank"&gt;getAdapter&lt;/a&gt;&lt;span&gt;。回答的太简洁了，完全没法理解，只好又去仔细研究ListView的代码，终于领会他的意思了。把其中&lt;/span&gt;&lt;a href="http://developer.android.com/reference/android/widget/ListView.html#addHeaderView(android.view.View)" target="_blank"&gt;addHeaderView&lt;/a&gt;&lt;span&gt;和&lt;/span&gt;&lt;a href="http://developer.android.com/reference/android/widget/ListView.html#setAdapter(android.widget.ListAdapter)" target="_blank"&gt;setAdapter&lt;/a&gt;&lt;span&gt;方法贴下来&lt;/span&gt;&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;span style="color: #008000;"&gt;/**&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&amp;nbsp;* Add a fixed view to appear at the top of the list. If addHeaderView is&lt;br /&gt;&amp;nbsp;* called more than once, the views will appear in the order they were&lt;br /&gt;&amp;nbsp;* added. Views added using this call can take focus if they want.&lt;br /&gt;&amp;nbsp;* &amp;lt;p&amp;gt;&lt;br /&gt;&amp;nbsp;* NOTE: Call this before calling setAdapter. This is so ListView can wrap&lt;br /&gt;&amp;nbsp;* the supplied cursor with one that that will also account for header&lt;br /&gt;&amp;nbsp;* views.&lt;br /&gt;&amp;nbsp;*&lt;br /&gt;&amp;nbsp;* &lt;/span&gt;&lt;span style="color: #808080;"&gt;@param&lt;/span&gt;&lt;span style="color: #008000;"&gt; v The view to add.&lt;br /&gt;&amp;nbsp;* &lt;/span&gt;&lt;span style="color: #808080;"&gt;@param&lt;/span&gt;&lt;span style="color: #008000;"&gt; data Data to associate with this view&lt;br /&gt;&amp;nbsp;* &lt;/span&gt;&lt;span style="color: #808080;"&gt;@param&lt;/span&gt;&lt;span style="color: #008000;"&gt; isSelectable whether the item is selectable&lt;br /&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #008000;"&gt;*/&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #0000ff;"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;void&lt;/span&gt; addHeaderView(View v, Object data, &lt;span style="color: #0000ff;"&gt;boolean&lt;/span&gt; isSelectable) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #0000ff;"&gt;if&lt;/span&gt; (mAdapter != &lt;span style="color: #0000ff;"&gt;null&lt;/span&gt;) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #0000ff;"&gt;throw&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; IllegalStateException(&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;"Cannot add header view to list -- setAdapter has already been called.");&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;FixedViewInfo info = &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; FixedViewInfo();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;info.view = v;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;info.data = data;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;info.isSelectable = isSelectable;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;mHeaderViewInfos.add(info);&lt;br /&gt;}&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&lt;span style="color: #008000;"&gt;/**&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&amp;nbsp;* Sets the data behind this ListView.&lt;br /&gt;&amp;nbsp;*&lt;br /&gt;&amp;nbsp;* The adapter passed to this method may be wrapped by a {&lt;/span&gt;&lt;span style="color: #808080;"&gt;@link&lt;/span&gt;&lt;span style="color: #008000;"&gt; WrapperListAdapter},&lt;br /&gt;&amp;nbsp;* depending on the ListView features currently in use. For instance, adding&lt;br /&gt;&amp;nbsp;* headers and/or footers will cause the adapter to be wrapped.&lt;br /&gt;&amp;nbsp;*&lt;br /&gt;&amp;nbsp;* &lt;/span&gt;&lt;span style="color: #808080;"&gt;@param&lt;/span&gt;&lt;span style="color: #008000;"&gt; adapter The ListAdapter which is responsible for maintaining the&lt;br /&gt;&amp;nbsp;*&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; data backing this list and for producing a view to represent an&lt;br /&gt;&amp;nbsp;*&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; item in that data set.&lt;br /&gt;&amp;nbsp;*&lt;br /&gt;&amp;nbsp;* &lt;/span&gt;&lt;span style="color: #808080;"&gt;@see&lt;/span&gt;&lt;span style="color: #008000;"&gt; #getAdapter()&lt;br /&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #008000;"&gt;*/&lt;/span&gt;&lt;br /&gt;@Override&lt;br /&gt;&lt;span style="color: #0000ff;"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;void&lt;/span&gt; setAdapter(ListAdapter adapter) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #0000ff;"&gt;if&lt;/span&gt; (&lt;span style="color: #0000ff;"&gt;null&lt;/span&gt; != mAdapter) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;mAdapter.unregisterDataSetObserver(mDataSetObserver);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;resetList();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;mRecycler.clear();&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #0000ff;"&gt;if&lt;/span&gt; (mHeaderViewInfos.size() &amp;gt; 0|| mFooterViewInfos.size() &amp;gt; 0) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;mAdapter = &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; HeaderViewListAdapter(mHeaderViewInfos, mFooterViewInfos, adapter);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;} &lt;span style="color: #0000ff;"&gt;else&lt;/span&gt; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;mAdapter = adapter;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt;其它的一些代码这里省略之...&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;}&lt;/div&gt;&lt;p&gt;从代码和注释里都可以很清楚的得知，addHeaderView一定要在setAdapter之前调用，如果不是，addHeaderView会抛出一个异常。Android为什么要这样做？因为，在setAdapter的时候，会针对我遇到的这种情况（也就是说，position不正确）做些特殊的处理。setAdapter在内部判断了当前ListView是否有Header或者Footer，如果没有，就直接使用参数传进来的adapter；如果有，则用一个decorated的HeaderViewListAdapter来替换参数。这个HeaderViewListAdapter的使命，就是排除Header和Footer，让position（当然也包括&lt;a href="http://developer.android.com/reference/android/widget/Adapter.html#getItem(int)" target="_blank"&gt;getItem&lt;/a&gt;,&amp;nbsp;&lt;a href="http://developer.android.com/reference/android/widget/Adapter.html#getItemId(int)" target="_blank"&gt;getItemId&lt;/a&gt;等）正确返回。&lt;/p&gt;&lt;p&gt;分析到这里，解决方案就出来了：不要直接使用我们声明的adapter，而是用ListView里的那个decorated adapter。获取它的方法就是调用getAdapter。当然，如果ListView没有Header和Footer，直接使用声明的adapter也没有问题，不过为了方便、避免以后出错，还是统一使用decorated adapter比较好。&lt;/p&gt;&lt;p&gt;把onItemClick改成下面这样，就可以了&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;@Override&lt;br /&gt;&lt;span style="color: #0000ff;"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;void&lt;/span&gt; onItemClick(AdapterView&amp;lt;?&amp;gt; parent, View v, &lt;span style="color: #0000ff;"&gt;int&lt;/span&gt; position, &lt;span style="color: #0000ff;"&gt;long&lt;/span&gt; id) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;doSomething(parent.getAdapter().getItem(position));&lt;br /&gt;}&lt;/div&gt;&lt;p&gt;&lt;span&gt;本文由Roy最初发表于：&lt;/span&gt;&lt;a href="http://blog.chengbo.net/2012/03/09/onitemclick-return-wrong-position-when-listview-has-headerview.html"&gt;http://blog.chengbo.net/2012/03/09/onitemclick-return-wrong-position-when-listview-has-headerview.html&lt;/a&gt;&lt;span&gt;，你可以在保持文章完整和保留本声明的情况下转帖、分发和印刷等。&lt;/span&gt;&lt;/p&gt;&lt;img src="http://www.cnblogs.com/chengbo/aggbug/2388242.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/chengbo/archive/2012/03/09/onitemclick-return-wrong-position-when-listview-has-headerview.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/chengbo/archive/2011/11/13/2246929.html</id><title type="text">准备再写写东西了</title><summary type="text">发现上一篇blog居然是07年的时候。。。太懒了，不过准备再写点东西了，主要是记录下自己在工作中的一些经验以及心得，也希望对其他人能有点帮助。最近工作是Android相关的，这玩意儿的中文资料太少而且质量超级低，自己磕磕碰碰研究了几个月，好歹入了点门，觉得还是记录分享下，也算是对中国的Android发展做出点贡献。。。（太看得起自己了吧？）</summary><published>2011-11-12T16:47:00Z</published><updated>2011-11-12T16:47:00Z</updated><author><name>chengbo</name><uri>http://www.cnblogs.com/chengbo/</uri></author><link rel="alternate" href="http://www.cnblogs.com/chengbo/archive/2011/11/13/2246929.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/chengbo/archive/2011/11/13/2246929.html"/><content type="html">&lt;p&gt;发现上一篇blog居然是07年的时候。。。太懒了，不过准备再写点东西了，主要是记录下自己在工作中的一些经验以及心得，也希望对其他人能有点帮助。&lt;/p&gt;&lt;p&gt;最近工作是Android相关的，这玩意儿的中文资料太少而且质量超级低，自己磕磕碰碰研究了几个月，好歹入了点门，觉得还是记录分享下，也算是对中国的Android发展做出点贡献。。。（太看得起自己了吧？）&lt;/p&gt;&lt;img src="http://www.cnblogs.com/chengbo/aggbug/2246929.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/chengbo/archive/2011/11/13/2246929.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/chengbo/archive/2007/05/02/Ajax-UpdatePanel-and-Viewstate-issue.html</id><title type="text">压缩 ViewState 后，与 UpdatePanel 的兼容问题</title><summary type="text">为了节省带宽，可能需要压缩一下 ViewState ，具体压缩的代码，网上一搜一大把，比如下面这段：publicclassCompressedViewStatePage:System.Web.UI.Page{conststringCompressedViewStateKey="__COMPRESSEDVIEWSTATE";protectedoverridevoidSavePageStateToPe...</summary><published>2007-05-02T10:09:00Z</published><updated>2007-05-02T10:09:00Z</updated><author><name>chengbo</name><uri>http://www.cnblogs.com/chengbo/</uri></author><link rel="alternate" href="http://www.cnblogs.com/chengbo/archive/2007/05/02/Ajax-UpdatePanel-and-Viewstate-issue.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/chengbo/archive/2007/05/02/Ajax-UpdatePanel-and-Viewstate-issue.html"/><content type="text">为了节省带宽，可能需要压缩一下 ViewState ，具体压缩的代码，网上一搜一大把，比如下面这段：publicclassCompressedViewStatePage:System.Web.UI.Page{conststringCompressedViewStateKey="__COMPRESSEDVIEWSTATE";protectedoverridevoidSavePageStateToPe...</content></entry><entry><id>http://www.cnblogs.com/chengbo/archive/2007/03/31/695555.html</id><title type="text">如何让 firefox 的窗口大小不再被网页脚本改变</title><summary type="text">有时候，firefox 的窗口大小会被你正在浏览的网页所改变（比如说点击 wordpress 后台“编辑 HTML”按钮的时候），这让我感到很不舒服，就像弹出广告一样，我相信大家都不会喜欢。其实有一个简单的方法可以让 firefox 的窗口不再被网页改变。 Mac/Linux 用户：点击 编辑 &gt; 参数设置；Windows 用户：工具 &gt; 选项 选择 内容 标签...</summary><published>2007-03-31T15:59:00Z</published><updated>2007-03-31T15:59:00Z</updated><author><name>chengbo</name><uri>http://www.cnblogs.com/chengbo/</uri></author><link rel="alternate" href="http://www.cnblogs.com/chengbo/archive/2007/03/31/695555.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/chengbo/archive/2007/03/31/695555.html"/><content type="text">有时候，firefox 的窗口大小会被你正在浏览的网页所改变（比如说点击 wordpress 后台“编辑 HTML”按钮的时候），这让我感到很不舒服，就像弹出广告一样，我相信大家都不会喜欢。其实有一个简单的方法可以让 firefox 的窗口不再被网页改变。 Mac/Linux 用户：点击 编辑 &gt; 参数设置；Windows 用户：工具 &gt; 选项 选择 内容 标签...</content></entry><entry><id>http://www.cnblogs.com/chengbo/archive/2007/02/27/fifty_two_proven_stress_reducers.html</id><title type="text">52个行之有效的减压方法</title><summary type="text">每天做15分钟的晨练。 前一天晚上就做好第二天的准备。 好记性不如烂笔头，有什么事都记下来。 不要做任何以后会让你说谎的事。 准备好备用钥匙。 做好演习，你的车，用具，家，人际关系随时都有可能出问题。 做好等待的准备，一本平装书可以让你在等待的过程中保持好心情。 拖延是压力之母，无论你明天要做什么，今天就做，无论你今天要做什么，现在就做。 计划先行，不要等到事情已经发生了，才去想解决办法。 不要对...</summary><published>2007-02-27T07:40:00Z</published><updated>2007-02-27T07:40:00Z</updated><author><name>chengbo</name><uri>http://www.cnblogs.com/chengbo/</uri></author><link rel="alternate" href="http://www.cnblogs.com/chengbo/archive/2007/02/27/fifty_two_proven_stress_reducers.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/chengbo/archive/2007/02/27/fifty_two_proven_stress_reducers.html"/><content type="text">每天做15分钟的晨练。 前一天晚上就做好第二天的准备。 好记性不如烂笔头，有什么事都记下来。 不要做任何以后会让你说谎的事。 准备好备用钥匙。 做好演习，你的车，用具，家，人际关系随时都有可能出问题。 做好等待的准备，一本平装书可以让你在等待的过程中保持好心情。 拖延是压力之母，无论你明天要做什么，今天就做，无论你今天要做什么，现在就做。 计划先行，不要等到事情已经发生了，才去想解决办法。 不要对...</content></entry><entry><id>http://www.cnblogs.com/chengbo/archive/2007/01/25/630107.html</id><title type="text">用Javascript检查Caps Lock是否按下</title><summary type="text">在输入密码的时候，用户不看键盘的话很难知道自己是否启用了大写，所以到经常因为大小写错了而被系统拒之门外。其实一段js代码就可以解决这个问题。Code highlighting produced byActipro CodeHighlighter(freeware)http://www.CodeHighlighter.com/--&gt;&lt;script&gt;functioncapLock(e){k...</summary><published>2007-01-25T04:44:00Z</published><updated>2007-01-25T04:44:00Z</updated><author><name>chengbo</name><uri>http://www.cnblogs.com/chengbo/</uri></author><link rel="alternate" href="http://www.cnblogs.com/chengbo/archive/2007/01/25/630107.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/chengbo/archive/2007/01/25/630107.html"/><content type="text">在输入密码的时候，用户不看键盘的话很难知道自己是否启用了大写，所以到经常因为大小写错了而被系统拒之门外。其实一段js代码就可以解决这个问题。Code highlighting produced byActipro CodeHighlighter(freeware)http://www.CodeHighlighter.com/--&gt;&lt;script&gt;functioncapLock(e){k...</content></entry><entry><id>http://www.cnblogs.com/chengbo/archive/2006/12/29/607239.html</id><title type="text">如何用C#和SQL获得当前月的第一天和最后一天</title><summary type="text">C#Code highlighting produced by Actipro CodeHighlighter (freeware)http://www.CodeHighlighter.com/--&gt;intyear=DateTime.Now.Year;intmonth=DateTime.Now.Month;DateTimefirstDayOfThisMonth=newDateTime(year,m...</summary><published>2006-12-29T09:31:00Z</published><updated>2006-12-29T09:31:00Z</updated><author><name>chengbo</name><uri>http://www.cnblogs.com/chengbo/</uri></author><link rel="alternate" href="http://www.cnblogs.com/chengbo/archive/2006/12/29/607239.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/chengbo/archive/2006/12/29/607239.html"/><content type="text">C#Code highlighting produced by Actipro CodeHighlighter (freeware)http://www.CodeHighlighter.com/--&gt;intyear=DateTime.Now.Year;intmonth=DateTime.Now.Month;DateTimefirstDayOfThisMonth=newDateTime(year,m...</content></entry></feed>
