在case标签中使用非静态字段

译文

原文地址:http://tools.android.com/tips/non-constant-fields

前言

找到这篇文章之前,主要是因为在以前一个公司项目中,实现点击事件接口的时候有这种写法。

public void onClick(View view){
  switch(view.getId()){
      case R.id.xx1:
      break;
      case R.id.xx2:
      break;
      case R.id.xx3:
      break;

  }
}

然后我们领导说这种写法存在这问题,新api下(具体说的那个api我给忘了)可能会出现id重复的情况,不严谨。然后使用这种写法:

public void onClick(View view){
  if(view.getId() == R.id.xx1){

  }else if(view.getId == R.id.xx2){

  }else if(view.getId == R.id.xx3){

  }
}

当时我是一脸懵逼,不置可否。回头就查了一下资料。找到这篇文章。

正文

在规则的android项目中, R文件里面生命的资源常量一般像

public static final int main=0x7f030004;

然而,截止 ADT 14,在library项目中,这些常量会被声明成:

public static int main=0x7f030004;

换言之,library项目中的资源常量不在是final的。原因其实很简单,当多个library项目结合的时候,这个值无法保证唯一性。
在ADT 14之前, 所有的字段是final的, 因为这个原因, 所有的library必须拥有资源而且需要将与main project关联的java代码重新编译。这样会影响性能,导致build变慢。这样做也阻止了不含source code 的library project的分发,限制了library项目的使用范围。

由于字段不再是final的 所以也就意味着library jars可以一次编译,直接在别的项目中重用。而且编译速度变快了。

然而,像下面这种资源代码就无法在library项目编译了。


int id = view.getId();
switch (id) {
    case R.id.button1:
        action1();
        break;
    case R.id.button2:
        action2();
        break;
    case R.id.button3:
        action3();
        break;
}

这是因为 switch语句要求case 标签,就像 R.id.button1,在编译的时候必须是常量。
(这个值会直接复制到.class文件中)。
为了解决这个问题,替换switch语句为if-else语句。幸好,这个操作在Eclipse是非常简单的。
仅仅是将光标放在switch关键词上,然后点击Ctrl-1(或者Cmd-1 on mac)。
使用之后将会将switch代码转换为如下:

int id = view.getId();
if (id == R.id.button1) {
    action1();
} else if (id == R.id.button2) {
    action2();
} else if (id == R.id.button3) {
    action3();
}

这是一般的UI代码,而且性能损失是微不足道的。
我们有一个探测器可以找到这种错误,而且会提供一个简单的介绍。
地址

总结
所以这么看来,因为library项目R文件中id不是final的,switch 语句需要将case 标签copy到.class 文件中。所以在library项目中switch语句中case标签不能为R.id.xxx。但是在非library中R.id.xxx 是final的,所以switch照用。

ps:
如果你的switch 语句像这样写:

switch (view.getId()) {

那么最终你将会有一个无效的if-else 链。而且每一个if检查都会请求调用view.getId()方法。所以要把view.getId()。方法放到前面来。(我擦我一直这么写的)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值