抽象新 API

假设您想使用 操作栏标签页 (action bar tabs) 作为应用程序的主要顶级导航形式。遗憾的是,ActionBar API 仅在 Android 3.0 或更高版本(API 级别 11+)中可用。因此,如果您想将应用程序分发到运行旧版本平台的设备上,则需要提供一种既支持较新 API,又能使用旧版 API 作为回退机制的实现。

在本节课中,您将构建一个使用抽象类和特定版本实现的标签页用户界面 (UI) 组件,以提供向后兼容性。本课将介绍如何创建新标签页 API 的抽象层,这是构建标签页组件的第一步。

准备抽象

Java 编程语言中的抽象涉及创建一或多个接口或抽象类来隐藏实现细节。对于较新的 Android API,您可以使用抽象来构建版本感知组件,这些组件在较新设备上使用当前 API,而在较旧设备上则回退到更兼容的旧 API。

使用这种方法时,您首先要确定希望以向后兼容方式使用的较新类,然后基于较新类的公共接口创建抽象类。在定义抽象接口时,应尽可能镜像较新的 API。这可以最大限度地提高前向兼容性,并使将来在不再需要时更易于丢弃抽象层。

为这些新 API 创建抽象类后,可以在运行时创建并选择任意数量的实现。出于向后兼容性的考虑,这些实现可以根据所需的 API 级别而有所不同。因此,一个实现可以使用最近发布的 API,而其他实现可以使用较旧的 API。

创建抽象标签页接口

为了创建标签页的向后兼容版本,您应首先确定应用程序所需的功能和特定 API。对于顶级部分标签页,假设您有以下功能需求:

  1. 标签页指示器应显示文本和图标。
  2. 标签页可以与 Fragment 实例关联。
  3. Activity 应能够监听标签页的更改。

提前准备这些需求可以让您控制抽象层的范围。这意味着您可以减少创建抽象层多个实现所花费的时间,并更快地开始使用新的向后兼容实现。

标签页的关键 API 位于 ActionBarActionBar.Tab 中。为了使您的标签页具备版本感知能力,需要对这些 API 进行抽象。本示例项目的需求要求向后兼容至 Eclair(API 级别 5),同时利用 Honeycomb(API 级别 11)中的新标签页功能。支持这两个实现及其抽象基类(或接口)的类结构图如下所示。

Class diagram of abstract base classes and version-specific implementations.

图 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 标签页方法

接下来,定义一个抽象类,允许您创建标签页并将其添加到 Activity 中,例如 ActionBar.newTab()ActionBar.addTab()

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);

    ...
}

在接下来的课程中,您将创建适用于旧版本和新版本平台的 TabHelperCompatTab 的实现。

您还应该阅读