android 不能试用switch

来源:互联网 发布:辛翠英诊所网络预约 编辑:程序博客网 时间:2024/04/28 13:32

Android Library中switch-case中调用资源id的问题

问题描述:

  当我们在Android依赖库中使用switch-case语句访问资源ID时会报如下图所示的错误。
      library error

分析原因:

报的错误是case分支后面跟的参数必须是常数,换句话说出现这个问题的原因是Android library中生成的R.java中的资源ID不是常数:

library error

  打开library中的R.java,发现确实如此,每一个资源ID都没有被声明为final:

library R.java

library R.java

  但是当你打开你的主工程,在onClick、onItemClick等各种回调方法中是可以通过switch-case语句来访问资源ID的,因为在主工程的R.java中资源ID都被声明为了final常量。

  project中能够通过switch-case语句正常引用资源ID:

project right

project right

  project中的R.java:

project R.java

project R.java

解决方案:

Google提供的一个方法就是把它转化为if-else语句,即在switch语句处 Ctrl+1 然后可以替换成if-else.语句。

  既然是由于library的R.java中的资源ID不是常量引起的,我们可以在library中通过if-else-if条件语句来引用资源ID,这样就避免了这个错误:

library use

library use

参考资料:

  为了进一步了解问题的具体原因,在万能的StackOverflow上还真搜到了这个问题:

In a regular Android project, constants in the resource R class are declared like this:

public static final int main=0x7f030004;

However, as of ADT 14, in a library project, they will be declared like this:

public static int main=0x7f030004;

In other words, the constants are not final in a library project. Therefore your code would no longer compile.

The solution for this is simple: Convert the switch statement into an if-else statement.

public void onClick(View src){    int id = src.getId();    if (id == R.id.playbtn){        checkwificonnection();    } else if (id == R.id.stopbtn){        Log.d(TAG, "onClick: stopping srvice");        Playbutton.setImageResource(R.drawable.playbtn1);        Playbutton.setVisibility(0); //visible        Stopbutton.setVisibility(4); //invisible        stopService(new Intent(RakistaRadio.this,myservice.class));        clearstatusbar();        timer.cancel();        Title.setText(" ");        Artist.setText(" ");    } else if (id == R.id.btnmenu){        openOptionsMenu();    }}

http://tools.android.com/tips/non-constant-fields

Tip
You can quickly convert a switch statement to an if-else statement using Eclipse's quick fix.

Click on the switch keyword and press Ctrl + 1 then select

Convert 'switch' to 'if-else'.

问题详见:switch case statement error: case expressions must be constant expression


库项目中对R.id资源的引用方式        

库项目

    Android库项目是保存共享的Android源代码和资源的开发项目。其它的Android应用项目可以引用库项目,并在构建时,将库项目编译后的源包含进.apk文件。多个应用项目可以引用同一个库项目,并且一个应用项目可以引用多个库项目。

 注意:你需要SDK工具r8或者更高的版本来完全支持所有Android平台版本的库项目。你可以使用Android SDK或者AVD管理器下载工具和平台,详细描述参见添加SDK组件。

    如果你的多个项目有公共的源代码和资源,你可以移动它们到一个库项目,这样一来维护交叉的应用和版本就更容易。下面是一些使用库项目的公共场景:

        •  如果你正在开发多个相关的应用,它们使用一些相同的组件。你可以从每个应用项目中移出冗余的组件到一个库项目,来创建一个单一的可重复使用的组件。

        •  如果你创建一个应用有免费和付费两个版本,你可以移动这两个版本的共同部分到一个库项目。这两个依赖库项目的项目,有它们各自不同的包名称,它们引用库项目,并且只提供两个应用版本之间不同的部分。

    在结构上,库项目和标准的Android应用项目相似。例如,在它的根目录下包含一个清单文件,/src,/res等目录。库项目能包含和标准 Android项目相同类型的源代码和资源,并且储存在相同的位置。例如,在库项目中,源代码也能通过R类访问它拥有的资源。

    但是,库项目和标准的Android应用项目的不同之处在于,你不能直接编译它到它自己的.apk文件,也不能在Android设备上运行它。同样地,你不能导出库项目到独立的JAR文件。做为替代,你必须直接地编译库项目,通过引用它的应用。

    当你构建依赖库项目的应用时,SDK工具编译库,并且合并源码到主项目,然后用合并的结果生成.apk文件。那些在应用和库中都有定义的资源ID,工具会 确保在应用中定义的资源有优先权,在库项目中的资源不会被编译到应用的.apk文件中。这使项目可以灵活的使用和重定义那些在库中定义的资源的行为和值。

    为了进一步的组织你的代码,你的应用可以引用多个库项目,然后指定每个库中资源的相对优先权。这让应用中实际使用的资源建立在累积的方式上。当两个被引用的库中定义了相同的资源ID时,工具会选择优先权高的资源并丢弃其它的。

    一旦你添加库项目到Android项目,你就可以设置它们的相对优先权。在构建时,这些库会按优先权从低到高一个一个的与应用合并。

    注意,一个库项目不能引用其它的库项目,并且,库项目与应用合并之前不相互合并。但是,库项目可以正常的导入外部JAR包。

开发注意事项

    当你开发库项目和相关的应用时,请记住以下几点:

        •  资源冲突

           由于工具会合并库项目和相关应用项目的资源,一个给定的资源ID可能被定义在这两个项目中,因此,工具从应用或者优先权高的库中选择资源并丢弃其它的资 源。当你开发应用时,应该意识到共同的资源ID可能会在多个项目中定义,并且会选择应用中的资源或者高优先权的库资源合并。

        •  使用前缀来避免资源冲突

           为避免公共资源ID的资源冲突,可以考虑使用前缀或其它一致的命名方案来保证资源在项目中的唯一(或者在所有项目中的唯一)。

        •  不能导出库项目到JAR文件

           库不能做为二进制文件分布(如:JAR文件)。因为库项目会被主项目以正确的资源ID编译。

        •  库项目可以包含JAR包

           你可以开发包含JAR包的库项目,但是,你要手动的编辑依赖它的应用项目的构建路径来添加JAR文件。

        •  库项目可以依赖JAR包

           你可以开发依赖外部包(如:地图外部包)的库项目。这样,相关的应用必须建立对应的目标来包含外部包(如:Google APIs组件)。还要注意库项目和相关的应用都必须在它们的清单文件的<uses-library>元素中声明外部包。

        •  库项目不能包含原始资产

           SDK工具不支持在库项目中作用原始资产(保存在assets/目录中的文件)。应用使用的所有资产资源必须存储在应用项目自身的assets/目录中。但是,保存在res/目录中的资源文件可以支持。

        •  平台版本必须低于或等于Android项目

           库被做为相关应用项目的一部分被编译,所以库项目中使用的API必须兼容Android库的版本来编译应用项目。总之,库项目使用的API等级应该等于或者低于应用中的。如果库项目比应用使用的API等级高,那么这个应用项目将不能编译。例如:一个使用Android API 1.5(API等级3)的库项目和使用Android 1.6(API等级4)或者2.1(API等级7)的项目在一起是完全可以的。

        •  库包名没有限制

           不要求库中包名称和应用中的包名称相同。

        •  每个库项目创建自己的R类

           当构建相关的应用项目时,库项目被编译并与应用项目合并。每个库都有自己的R类,根据库的包名称命名。R类由主项目生成,在库项目中,它被创建在所有需要的包中,包含主项目包和库包。

        •  库项目的存储位置

           对于相关应用项目来说,没有具体要求库项目存储在哪里,只要应用项目能通过一个相对的链接来引用库项目。最重要的就是,主项目能通过一个相对的链接来引用库项目。

 

注:库工程里不能用switch(view.getId())来判断元素的ID,因为R.id在库工程里是变量,解决方法参见:http://tools.android.com/tips/non-constant-fields

0 0
原创粉丝点击