编写向后兼容的Android代码
我正在编写一个应用程序,它只使用最新API级别的某些函数和类 – 16,但是我希望它在API级别为15的设备上运行时没有错误。
我们来举几个例子。 一个新的类: Android.widget.Advanceable
和一个新的/重命名的方法: View.setBackground()
:
我可以做这样的事情:
Advanceable myAdvanceable = ...; if (android.os.Build.VERSION.SDK_INT >= 16) { myView.setBackground(...); myAdvanceable.advance(); } else { myView.setBackgroundDrawable(...); // The old function name. // Don't bother advancing advanceables. }
如果我设置15的minSdk,但build立目标是16(即在项目属性 – > Android),它将实际编译没有错误。 至less有一些时间。 Eclipse对这些错误有些随意,有时候会说“setBackground()只能在API级别> = 16”或类似的情况下才可用,但是如果我只是清理项目,这些错误就会消失。
所以我的问题是,我允许这样做吗? 如果我在API 15级设备上运行代码,会不会崩溃? 它只会崩溃,如果它实际上得到16代码? Eclipse为什么不阻止我构build它?
编辑1
感谢您的答案,我想这个问题应该是:为什么不皮棉警告我使用新的API?
我在清单中有这个,并且正在使用API级别16的函数,但它仍然不会警告我:
<uses-sdk android:minSdkVersion="15" android:targetSdkVersion="16"/>
另外我还不确定整个类是什么时候是API级别的新类,比如Advanceable
。 特别是如果我使用它们作为成员variables。
编辑2
答案竟然是“Eclipse就像地狱一样”,但是Nico的回答也非常有帮助。
内联Api错误是ADT的新function,Eclipse运行Lint(我想别的也许可能)来分析你的代码,并把这些错误/警告内联。 当您有关于优化或最佳实践的警告或提示时,也适用于xml布局。 您可以使用批注来抑制类或特定方法中的这些错误。
@TargetApi(16)
@SuppressLint( “NewApi”)
您在这里放置的示例代码中存在一个问题,除了API级别检查,您在代码中有一个Advanceable实例,在API <16中不起作用,所以检查API级别仅在调用新方法时有用,在IF块之外引用新的API类。
我发现一种可以接受的方法是创build一个抽象类和两个实现,然后实例化正确的实现,您可以使用静态方法使用工厂类。
例如,要创build一个在内部使用一些新的API类和方法的视图,您需要:
1 – 创build抽象类:
public abstract class CustomView { public abstract void doSomething(); }
- 与所有API兼容的通用实现
- 在这里定义抽象方法来分割实现
2 – 遗留的实现
public class CustomLegacyView extends CustomView { public void doSomething(){ //implement api < 16 } }
- 实现API <16的抽象方法
3 – API 16的实现
@TargetApi(16) public class CustomL16View extends CustomView { Advanceable myAdvanceable; public void doSomething(){ //implement api >= 16 } }
- 使用注解@TargetApi(16)
- 实现API> = 16的抽象方法
- 你可以在这里引用16级的类(但不能在CustomView中)
4 – 工厂类
public class ViewFactory { public static CustomView getCustomView(Context context) { if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { return new CustomL16View(context); }else{ return new CustomLegacyView(context); } } }
使用更新的构build目标是一个常见的做法,并保证在适当的环境下调用更新的API。 Google甚至在ADT 17之后还添加了@TargetApi()
注释,为有条件加载的代码指定本地覆盖。
请参阅Lint API检查以获取更多详细信息。
1.您有Target Api
和Minimum SDK
属性来定义您定位的设备types, 以及哪个设备将运行的最less的Api版本 。
2. Target Api
是应用程序运行Fullfunction的 Target Api
,而Minimum SDK
将使应用程序运行一些妥协,因为可能有更低的API版本不具有更高版本的function 。