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

来源:互联网 发布:时时彩软件urssc 编辑:程序博客网 时间:2024/06/05 04:31

译文

原文地址: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()。方法放到前面来。(我擦我一直这么写的)

原创粉丝点击