2015

2014年就这样过去了。刚刚去机场把lulu送回东京,也没什么心情写总结。心神不宁地网上乱转,都是上海跨年踩踏的消息。

这一年换了个工作,算是一个比较大且开心的事情。出远门玩了几个地方,东京魔都阿拉斯加还有大峡谷什么的。花了5个月看了本Steven Pinker的大部头「The Better Angels of Our Nature」,还是云里雾里的。今年演出明显看得少了,财务问题好像略微改善了些。还有些别的,其实也挺重要的,但还是留给自己好了。

2015年,也没有什么特别想在这里说的,但感觉要做的事情还是很多的,一件一件慢慢地来吧。

在Android项目中启用ProGuard

最近不得不面对Android 65k method limit问题,所以启用ProGuard来除去一些没有被调用到的方法来降低被引用的方法总数(referenced method count)是一个不错的暂时的解决办法。

启用ProGuard
如何启用其实非常简单。如果项目是用Maven作为build system的,在app项目的pom文件里的android maven插件的节点下加入:

<proguard>
    <skip>false<skip>
    <config>proguard-project.txt</config>
</proguard>

proguard-project.txt即是配置文件,待会儿会详细讲。如果是Gradle的话,可以在buildTypes里加入1

runProguard true
proguardFiles file('proguard-project.txt')

启用后,每次build一般都会生成四份文件,dump.txt/mapping.txt/seeds.txt以及usage.txt。

  • dump.txt:包含了最终在.apk文件里的类结构
  • mapping.txt:如果启用了混淆代码的话(默认是开启的),这个文件里会列出原来的类/方法/成员的名字与混淆后的对应
  • seeds.txt:列出了没有混淆的类及其成员
  • usage.txt:列出了那些被去除的代码

配置ProGuard
在Android SDK的tools/proguard文件夹下有两个默认的配置文件,proguard-android-optimize.txt和proguard-android.txt。从文件名中可以看出一个是启用了优化另一个则是普通的配置文件。按需选择一个对一般的app来讲就足够用了。不过如果是因为64k问题而选择proguard的话,肯定也是个不一般的app,所以需要根据自己app的情况添加一些规则。这里有完整的ProGuard用法。那接下来说下我自己添加的几条规则供参考:

  • Warning: can’t find superclass/interface/referenced class:一般来讲,这是启用proguard最先会遇到的警告。这个警告说的是无法找到父类/借口/被引用的类,出现这个有可能是真的所需要的类没有被找到,需要指定包含这些类的jar的所在位置,但对于Android来说,很多情况下只需要使用-dontwarn规则来关闭这些警告就可以,因为在Android的编译过程中会自动指定所引用的jar。
  • -dontobfuscate:混淆代码后会使debug非常困难。即是是发布的版本,如果使用Crashlytics,最后收到的crash报告也是混淆后的,还是会使debug变得非常困难。虽然可以用retrace脚本来转换混淆后的stack trace,但是这样多做一步并不是很值得。不过如果你的app因为安全原因必须要混淆代码,那也只有这条路可以走了。
  • Automated Instrumentation Testing:如果你的项目里有Instrumentation测试,需要加入-keep public class * extends android.app.Application这样一条规则。因为每个测试项目会自动生成一个android.app.Application类,而ProGuard则认为这些Application类没有在任何地方被调用就自动剔除了,所以测试就没法在ci服务器上运行。这点我当时花了一天时间才最后解决的。:-(
  • Play Services:这个庞大的库本身就占用了大概两三万的方法数,虽然这个库在Android开发中算是必须的,但其实大部分都未必用得到,于是就造成了浪费。Google对于这个库有它自己推荐的规则,直接添加进来就可以。好消息是Play Services下一个版本6.5将会模块化。
  • Reflection:用到reflection的地方也是需要添加规则来保留这些类的。

Android 65k
现在我们来吐槽下这个65k问题Davlik是Android的运行时,其指令里有一个method reference index的变量,就是Davlik里最多能调用的方法数量。Android从出生到现在这个变量的大小从来没有改变过,就是16 bit,也就是令人发指的65536,从此,臭名昭著的65k限制由此而生。除了使用ProGuard外,还有一种比较流行的办法是multi-dex。

Ambitious New Android Developer

Multi-dex
随着app体积越来越大,即使用了ProGuard也还是会导致引用的方法数超过65536,于是有人就想到那我就编译多个dex文件,其中一个是主要的dex文件,然后在运行时再载入其他所需的dex。在Android新的运行时ART发布之前,这是非常繁琐低效的。随着ART的发布,multi-dex有了原生的支持,多个dex文件会在app安装的时候被编译成一个.oat文件让ART来执行,所以也不需要在运行时才载入所需的dex。而在ART之前的版本,Google也发布了支持multidex的库。详细的设置可以看这里:Configuring Your App for Multidex with Gradle。但这个归根到底还是一个hack,而且还是有很多限制,比如不怎么支持Android 4.0之前的版本,极大地增加了编译时间等等。

虽然看上去65k问题的实质很简单,但既然Google这么多年都没有能够修复,或许这真的是一个很难搞的bug。但话又说回来,随着移动领域越发地火热以及迅速地发展,不很好地解决这个问题实在很说不过去。


  1. Gradle指定ProGuard配置文件的时候还有类似getDefaultProguardFile('proguard-android.txt'),'proguard-rules.pro'这样的写法,直接从SDK里找到默认的配置文件再与自己项目特定的配置文件整合在一起,这点是Android Maven插件还无法做到的。

如何在终端下使用Swift

在安装完Xcode 6 Beta之后,首先先把Xcode的Developer tools切换到Xcode 6下。

sudo xcode-select --switch /Applications/Xcode6-Beta.app/Contents/Developer

然后在iTerm/Terminal下输入xcrun swift即可!

Swift初探

初探Swift

在前几天的WWDC上,Apple宣布了Swift这个新的编程语言。花了一点时间读了点文档玩了会儿,总结下一些值得一提的地方。因为也是刚刚接触,如果哪里有错,还请悉心指出。

  • 类型推导:既然Swift作为编译时静态的语言,大部分时候就可以由编译器推断出变量类型,于是比如就可以用var关键字来声明变量以减少拼写,增加代码的可读性。当然,在编译器无法推断出类型的时候,还是需要显示声明对象的类型。

  • 可变字符串:在JAVA/C#里,字符串默认是不可变的,即对于一个字符串对象进行修改,都会创建一个新的字符串对象,而在Swift,如果是声明的变量就可以直接对其内容进行修改。

  • ..来表示一段范围:这个跟Ruby类似,比如循环就可以这样表达:for i in 0..3

  • 多个返回值:跟C#的Tuple类似,不过一般来讲在OOP里,如果需要用到多个返回值的情况,很有可能是设计不当,没有用一个类型来封装这些返回值。但又不得不承认有时候的确这样也会比较方便。

  • 枚举类型:这次Swift的枚举类型功能强大,不仅支持Int和字符串,还支持任意类型的枚举,甚至Swift里的Optional类型也是建立在枚举类型上的。具体可以查看文档的Enumerations章节

  • 闭包:即Clousure, 也就是Lambda表达式/匿名函数/Block,无需多说了。

  • Protocol:或许对于Objective-C程序员来讲并不陌生,但其实也就是OOP里的接口。

  • 结构体和类(Struct and Class):跟C#类似,结构体一般被内存分配在栈上,而类在堆上,结构体值传递,类则引用传递。

  • 属性:跟C#类似,由编译器来生成类型的成员以及getter/setter,不过Swift在属性上还有Observer来反应值的改变。

  • 泛型:是类似C#的真泛型,不像JAVA的泛型,总是需要装箱拆箱,没有很强的类型安全,性能也相比较差。作为一门新的语言,不用考虑向后兼容,这点也是应该的。:p

  • dynamicType:Swift是编译时静态运行时动态的语言,即有些类型在运行时才确定,具体可以看文档的Dynamic Type Expression这一章节。

  • 扩展方法:跟C#类似,可以自由地扩展类型,只是语法上比C#更简洁一些。

  • Optional:就是C#里的Nullable,因为有些类型本身不支持nil的赋值,所以如果在这类类型声明的时候加上?即声明了一个optional value,比如var a: Int? = nil,这样value就是一个初始值为空的Int?类型。有些人会问那不如直接初始值赋为-1好了。但是既然给一个变量赋了一个值,就代表这个值对于程序的上下文是有意义的,而把这个变量设为nil就代表这个变量在这段程序里是暂时没有意义的。另外有了Optional之后,由于每次都需要检查是不是nil会造成if-else语句的层叠影响代码可读性,Swift的Optional Chaining就很好的解决了这个问题。

  • weak和unowned关键字来表达这种情况,以便编译器在合适的时候生成代码回收对象。

总的来说,现代语言该有的Swift都包含了进去,使得写代码效率提高很多,代码也更加易读。这一点上我还是很兴奋的。至于所谓的坑,其实只是语言设计时候的各种取舍。比如JAVA的泛型之所以这么设计就是为了向后兼容,而当C# 2.0推出泛型的时候,就不考虑这一点。再比如Swift的Optional最近就一直让人很困惑受到很多人的吐槽,典型的比如这条推里写的,其实就是没有理解Optional。这条推里的代码声明了一个Optional的变量并且赋了有意义的值,却没有弄明白在if语句里判断这个变量其实是判断这个Optional的变量是不是nil,而不是判断这个变量的值(因为可能这个变量根本没有值)。

至于学习,最好的办法就是照着文档写代码了。目前官方主要有The Swift Programming LanguageSwift Standard Library ReferenceUsing Swift with Cocoa and Objective-C。而这次WWDC里也有很多session是介绍Swift的,还涵盖了文档里没有介绍的一些东西,非常值得一看。全部的视频都已经在上传到了WWDC14的网站。另外有不懂的,也可以去Stackoverflow的swift-language标签下问问题或者看看别人的回答。

以上说的这些,只是基于还在pre-release的文档,所以还会有变化,但初看下来Swift是一门设计得不错的语言。尽管现在看上去只是为了开发iOS和OS X软件服务的,个人觉得不久之后或许就是一门general purpose的语言,因为这门语言本身是有这样的潜力的。另外还希望苹果能开源与Swift相关的工具,比如编译器、REPL等等。C#的编译器都开源了,厨子!

最后引用Swift的设计者Crhis Lattner的一条推:

微软更新.Net源代码检索网站

微软最近更新了查看.Net源代码的网站,.Net Framework团队也发了篇blog: A new look for .NET Reference Source

新的网站体验非常不错,搜索响应非常迅速,还支持”Go to Definition”跟”Find All References”,URL即是链接到某个assembly或者是某个文件的第几行,比如像这样:/#System.Core,或者是像这样:/#mscorlib/system/environment.cs#56。这些都是由还在CTP阶段的Roslyn API(微软的.Net compiler as service)项目构建。另外.Net源代码也可以下载下来,还附带了.sln的solution文件,方便在Visual Studio里直接查看。目前的代码是基于.Net 4.5.1这个版本的,.Net团队意思是以后网站会随着.Net重大更新而同步更新。

这次的更新,还带来了直接在Visual Studio里debug .Net代码的功能。如何在VS2013里设置可以戳这里:”How to configure Visual Studio for debugging .NET framework“。

目前,社区里也有人做了一个Visual Studio的插件,就是按F12直接转到这个网站上相应的代码。

最后值得一提的是.Net源代码的license是MS-RSL(MS Reference Source License)。

“Reference use” means use of the software within your company as a reference, in read only form, for the sole purposes of debugging your products, maintaining your products, or enhancing the interoperability of your products with the software, and specifically excludes the right to distribute the software outside of your company.

2013年度OPT+H1B报税

又是一年报税季,本着早报早拿钱的心态,今年一拿到W2就开始着手报税了,前不久刚拿到退税,现在过来总结下。

2013年度,我是10月份从F1(OPT)转到了H1B,但是因为过去三年以H1B身份在美国没满183天,所以还是以非居民(Non-resident)身份报税。有些人会申请延期报税以便用dual-status身份报,可以多拿点退税,但是嫌麻烦,就算了。我就一张W2,也没有股票啊什么的,所以就还是用的1040NR-EZ

这样的话,报税过程跟去年几乎没有区别,仍然是参照IRS的官方指南杜克大学中文报税指南,以及需要附上证明是非居民的8843表,然后就是各项加加减减了。因为前10个月是OPT,所以中美5000 treaty还是适用的。

今年有个地方倒是折腾了很久,就是收到了一张加州政府寄来的1099-G。这是去年州政府退税的证明,于是困扰了我很久到底应不应该报上去。上面说如果去年用了Itemized Deduction就要报,用Standard Deduction的就不用报。我在这两个deduction上纠缠了很久,因为Standard Deduction仅适用于居民,而我又不记得去年报税有Itemized Deduction这一说。但其实每年非居民填1040NR-EZ的时候,Line 11上填的就是包含州税的Itemized Deduction,所以,今年就需要将1099-G上的数字填到1040NR-EZ上的Line 4里。之后,就是各项数字做加减法。填完之后,连同跟你身份有关的文件复印件寄过去就好了。

报完联邦税之后,报加州税就是非常简单的,还是跟去年一样,去加州税务网站如实填表就行了,大概一个礼拜左右就拿到了。联邦因为我是邮寄的,所以略微慢了一点,不过大概三个礼拜左右也拿到了退税。

在洛杉矶申请日本签证

打算4月底的时候回国休假三个礼拜,顺便把工作签证给转好。于是心思活络地就想要么先取道东京玩几天,而且早就听闻在美帝申请去日本的旅游签证比在国内申请要简单得多。订机票的时候,先看multiple city的路线发觉也并没有很划算,于是就先买了LA到东京再从上海飞回LA的往返票,然后趁着东航促销,再买从东京飞回上海的机票。

鉴于像这种情况,去日本签证性价比最高的就是过境签(Transit Visa),就是适合日本只是经停一下待几天再前往第三方国家的,而且签证费也便宜只要9美刀。虽然过境签是日本认可的,但是查日本驻洛杉矶领事馆官方网站上并没有列出如何办过境签,而只是列出了短期旅游签。在查了一番别的领事馆网站以及打电话咨询了洛杉矶领事馆之后,其实办理需要的材料跟短期旅游签证是一样的,但是在签证申请表上”Purpose of visit to Japan”那里需要注明transit去哪里而已,另外过境签发的应该是单次入境且最多待15天的签证,然后签证颁发3个月内不用即失效,而短期旅游签证根据行程可能会多次入境或者可以待更久。

签证所需的材料就按网站上给的短期旅游签证需要的材料准备就行:

  • 有效护照
  • 2寸X2寸照片一张(贴在签证申请表上就行,不用额外的)
  • 签证申请表
  • 所有航班的行程单(重要的是必须要有你的名字、出入境的日期和机场)
  • 证明你在美国合法身份的材料(像我H1B的话就是I-797 Approval Notice和Notice of Action,学生就是I-20,绿卡就是带着绿卡,美国公民的话你不需要签证)
  • 最新的银行statement(我是BOA的eBanking,直接去ATM选打印full statement就是截止到当天的最近交易记录,我还带了份上个月的,但是最后签证的时候他们说不用。至于余额要多少,其实完全根据你将在日本待多少天定的)
  • 因为我工作了,就带了最近两张pay check
  • 宾馆的预订确认单(如果不确定住哪,可以先找那种会full refund或者入住当天才付钱的酒店先订好,注意确认单上也必须要有你的名字以及check-in、check-out的日期)
  • 旅行每天详细的计划(签证的时候会查是不是每天都写了,但是不知道他们会不会细看)

另外,

  • 有个很热门的问题就是要不要担保人的邀请函。其实很tricky,如果你说你是去日本看朋友的,那就要对方的邀请函,如果你说你是去旅游的,那就不要,可以省去很多麻烦。
  • 签证申请表上有个问题”ID No. issued to you by your government”,我的理解就是身份证,但其实无所谓。
  • 第二页的监护人按照自己的情况填,邀请人的话,旅游/过境签都不用填。
  • 一般的情况,照这样准备就没问题了,反正最保险的就是先网站上看好然后打个电话过去问下。
  • 关于递签,一般在你附近有领事馆的话,就不能递签,必须面签。洛杉矶的面签速度很快,我的经验就是1点半过后去基本没有人,直接过去交材料,签证官会审核一下,大概20分钟就完事了,一般隔一天就能拿到,我周二去签的,周四就拿到了。

日本驻洛杉矶领事馆在臭名昭著的downtown。

周边停车最划算的其实是Grand Central Market自带的停车场,只要在那里消费满10块钱,就可以免费停一个小时,停车场的地址:

从S Hill街的门口出来走楼梯或者乘Angel’s Flight(暂时关了)上去就行,别忘记要先在门口check-in。