抽象化新 API
使用集合让一切井井有条
根据您的偏好保存内容并对其进行分类。
假设您希望使用操作栏标签页作为应用中的顶层导航的主要形式。很遗憾,ActionBar
API 仅适用于 Android 3.0 或更高版本(API 级别 11 及更高级别)。因此,如果您希望将应用分发到搭载更低版本平台的设备,则需要提供支持较新 API 的实现,同时提供使用较旧 API 的回退机制。
在本课程中,您会构建一个标签页式界面组件,该组件使用具有版本特定实现的抽象类以提供向后兼容性。本节课介绍如何为新标签页 API 创建抽象层,这是构建标签页组件的第一步。
为抽象化做准备
Java 编程语言中的抽象化涉及创建一个或多个接口或抽象类来隐藏实现细节。对于新的 Android API,您可以使用抽象化来构建版本感知组件,以在新设备上使用新的 API,而在旧设备上回退到更兼容的旧 API。
使用此方法时,首先要确定要以向后兼容的方式使用哪些新类,然后根据新类的公共接口创建抽象类。在定义抽象接口时,应尽可能镜像新 API。这可以最大限度地提高向前兼容性,并且在未来不再需要抽象层时,也更容易将其丢弃。
在为这些新 API 创建抽象类之后,可以在运行时创建和选择任意数量的实现。为了确保向后兼容性,这些实现可能会因所需的 API 级别而异。因此,一种实现可能使用最近发布的 API,而其他实现可能使用旧 API。
创建抽象标签页接口
要创建标签页的向后兼容版本,应首先确定您的应用需要哪些功能和特定的 API。对于顶部的标签页,假设您具有以下功能要求:
- 标签页标识应显示文本和图标。
- 标签页可以与 fragment 实例关联。
- Activity 应该能够监听标签页更改。
提前准备好这些要求可让您控制抽象层的范围。这意味着您可以花更少的时间创建抽象层的多个实现,并更快开始使用新的向后兼容实现。
标签页的主要 API 位于 ActionBar
和 ActionBar.Tab
中。这些是为了使标签页能够感知版本而抽象化的 API。此示例项目的要求是向后兼容 Eclair(API 级别 5),同时充分利用 Honeycomb(API 级别 11)中的新标签页功能。下面显示了支持这两种实现及其抽象基类(或接口)的类结构图。
图 1. 抽象基类和特定于版本的实现的类结构图。
抽象 ActionBar.Tab
如需开始构建标签页抽象层,您需要先创建一个代表标签页、镜像 ActionBar.Tab
接口的抽象类:
Kotlin
sealed class CompatTab(val tag: String) {
...
abstract fun getText(): CharSequence
abstract fun getIcon(): Drawable
abstract fun getCallback(): CompatTabListener
abstract fun getFragment(): Fragment
abstract fun setText(text: String): CompatTab
abstract fun setIcon(icon: Drawable): CompatTab
abstract fun setCallback(callback: CompatTabListener): CompatTab
abstract fun setFragment(fragment: Fragment): CompatTab
...
}
Java
public abstract class CompatTab {
...
public abstract CompatTab setText(int resId);
public abstract CompatTab setIcon(int resId);
public abstract CompatTab setTabListener(
CompatTabListener callback);
public abstract CompatTab setFragment(Fragment fragment);
public abstract CharSequence getText();
public abstract Drawable getIcon();
public abstract CompatTabListener getCallback();
public abstract Fragment getFragment();
...
}
您可以在此处使用抽象类代替接口,以简化常用功能(例如标签页对象与 Activity 的关联等)的实现(未在代码段中显示)。
抽象 ActionBar 标签页方法
接下来,定义一个抽象类,该类允许您创建标签页并将其添加到诸如 ActionBar.newTab()
和 ActionBar.addTab()
的 Activity 中:
Kotlin
sealed class TabHelper(protected val activity: FragmentActivity) {
...
abstract fun setUp()
fun newTab(tag: String): CompatTab {
// This method is implemented in a later lesson.
}
abstract fun addTab(tab: CompatTab)
...
}
Java
public abstract class TabHelper {
...
public CompatTab newTab(String tag) {
// This method is implemented in a later lesson.
}
public abstract void addTab(CompatTab tab);
...
}
在接下来的课程中,您将创建在新旧平台上都适用的 TabHelper
和 CompatTab
实现。
另请阅读
本页面上的内容和代码示例受内容许可部分所述许可的限制。Java 和 OpenJDK 是 Oracle 和/或其关联公司的注册商标。
最后更新时间 (UTC):2025-07-27。
[null,null,["最后更新时间 (UTC):2025-07-27。"],[],[],null,["# Abstract the new APIs\n\nSuppose you want to use [action bar tabs](/guide/topics/ui/actionbar#Tabs) as the primary form of top-level navigation in your application. Unfortunately, the [ActionBar](/reference/android/app/ActionBar) APIs are only available in Android 3.0 or later (API level 11+). Thus, if you want to distribute your application to devices running earlier versions of the platform, you need to provide an implementation that supports the newer API while providing a fallback mechanism that uses older APIs.\n\nIn this class, you build a tabbed user interface (UI) component that uses abstract classes with version-specific implementations to provide backward-compatibility. This lesson describes how to create an abstraction layer for the new tab APIs as the first step toward building the tab component.\n\nPrepare for abstraction\n-----------------------\n\n[Abstraction](https://en.wikipedia.org/wiki/Abstraction_(computer_science)) in the Java programming language involves the creation of one or more interfaces or abstract classes to hide implementation details. In the case of newer Android APIs, you can use abstraction to build version-aware components that use the current APIs on newer devices, and fallback to older, more compatible APIs on older devices.\n\nWhen using this approach, you first determine what newer classes you want to be able to use in a backward compatible way, then create abstract classes, based on the public interfaces of the newer classes. In defining the abstraction interfaces, you should mirror the newer API as much as possible. This maximizes forward-compatibility and makes it easier to drop the abstraction layer in the future when it is no longer necessary.\n\nAfter creating abstract classes for these new APIs, any number of implementations can be created and chosen at runtime. For the purposes of backward-compatibility, these implementations can vary by required API level. Thus, one implementation may use recently released APIs, while others can use older APIs.\n\nCreate an abstract tab interface\n--------------------------------\n\nIn order to create a backward-compatible version of tabs, you should first determine which features and specific APIs your application requires. In the case of top-level section tabs, suppose you have the following functional requirements:\n\n1. Tab indicators should show text and an icon.\n2. Tabs can be associated with a fragment instance.\n3. The activity should be able to listen for tab changes.\n\nPreparing these requirements in advance allows you to control the scope of your abstraction layer. This means that you can spend less time creating multiple implementations of your abstraction layer and begin using your new backward-compatible implementation sooner.\n\nThe key APIs for tabs are in [ActionBar](/reference/android/app/ActionBar) and [ActionBar.Tab](/reference/android/app/ActionBar.Tab). These are the APIs to abstract in order to make your tabs version-aware. The requirements for this example project call for compatibility back to Eclair (API level 5) while taking advantage of the new tab features in Honeycomb (API Level 11). A diagram of the class structure to support these two implementations and their abstract base classes (or interfaces) is shown below.\n\n**Figure 1.** Class diagram of abstract base classes and version-specific implementations.\n\nAbstract ActionBar.Tab\n----------------------\n\nGet started on building your tab abstraction layer by creating an abstract class representing a tab, that mirrors the [ActionBar.Tab](/reference/android/app/ActionBar.Tab) interface: \n\n### Kotlin\n\n```kotlin\nsealed class CompatTab(val tag: String) {\n ...\n abstract fun getText(): CharSequence\n abstract fun getIcon(): Drawable\n abstract fun getCallback(): CompatTabListener\n abstract fun getFragment(): Fragment\n\n abstract fun setText(text: String): CompatTab\n abstract fun setIcon(icon: Drawable): CompatTab\n abstract fun setCallback(callback: CompatTabListener): CompatTab\n abstract fun setFragment(fragment: Fragment): CompatTab\n ...\n}\n```\n\n### Java\n\n```java\npublic abstract class CompatTab {\n ...\n public abstract CompatTab setText(int resId);\n public abstract CompatTab setIcon(int resId);\n public abstract CompatTab setTabListener(\n CompatTabListener callback);\n public abstract CompatTab setFragment(Fragment fragment);\n\n public abstract CharSequence getText();\n public abstract Drawable getIcon();\n public abstract CompatTabListener getCallback();\n public abstract Fragment getFragment();\n ...\n}\n```\n\nYou can use an abstract class instead of an interface here to simplify the implementation of common features such as association of tab objects with activities (not shown in the code snippet).\n\nAbstract ActionBar tab methods\n------------------------------\n\nNext, define an abstract class that allows you to create and add tabs to an activity, like [ActionBar.newTab()](/reference/android/app/ActionBar#newTab()) and [ActionBar.addTab()](/reference/android/app/ActionBar#addTab(android.app.ActionBar.Tab)): \n\n### Kotlin\n\n```kotlin\nsealed class TabHelper(protected val activity: FragmentActivity) {\n ...\n\n abstract fun setUp()\n\n fun newTab(tag: String): CompatTab {\n // This method is implemented in a later lesson.\n }\n\n abstract fun addTab(tab: CompatTab)\n\n ...\n}\n```\n\n### Java\n\n```java\npublic abstract class TabHelper {\n ...\n\n public CompatTab newTab(String tag) {\n // This method is implemented in a later lesson.\n }\n\n public abstract void addTab(CompatTab tab);\n\n ...\n}\n```\n\nIn the next lessons, you create implementations for `TabHelper` and `CompatTab` that work across both older and newer platform versions.\n\n### You should also read\n\n- [Action Bar](/guide/topics/ui/actionbar)\n- [Action Bar Tabs](/guide/topics/ui/actionbar#Tabs)"]]