新しい API を抽象化する

アクションバー タブをアプリの最上位ナビゲーションのメインフォームとして使用したいとします。しかし、残念ながら ActionBar API は Android 3.0 以降(API レベル 11 以上)でしか利用できません。したがって、古いバージョンのプラットフォームを実行するデバイスにアプリを配布する場合は、新しい API をサポートする実装を提供する一方で、古い API を使用する代替メカニズムも提供する必要があります。

このトレーニング クラスでは、バージョン固有の実装で抽象クラスを使用し、下位互換性を持つタブ付きユーザー インターフェース(UI)コンポーネントを構築します。このレッスンでは、タブ コンポーネントを構築するための最初のステップとして、新しいタブ API の抽象化レイヤを作成する方法について説明します。

抽象化の準備

Java プログラミング言語の抽象化では、実装の詳細を隠蔽する 1 つ以上のインターフェースまたは抽象クラスを作成します。新しい Android API の場合、抽象化を使用して、新しいデバイスでは最新の API を使用し、古いデバイスではより互換性が高い古い API を代替使用する、バージョン対応コンポーネントを構築できます。

このアプローチを採用する場合は、まず、下位互換性のある方法で使用できる新しいクラスを決定し、次に、新しいクラスの公開インターフェースに基づいて抽象クラスを作成します。抽象化インターフェースを定義する際に、できるだけ新しい API を反映させる必要があります。それにより、上位互換性が最大化され、不要になった抽象化レイヤを将来破棄することが容易になります。

こうした新しい API 用の抽象クラスを作成したら、実行時に任意の数の実装を作成して選択できるようになります。下位互換性を確保するため、必要な API レベルに応じて異なる実装を用意できます。つまり、ある実装では最近リリースされた API を使用し、他の実装では古い API を使用できます。

抽象タブ インターフェースの作成

下位互換性のあるタブのバージョンを作成するには、まず、アプリに必要な機能と API を決定します。たとえば、最上位セクションのタブの場合に、次の機能要件があるとします。

  1. タブ インジケーターにテキストとアイコンを表示する。
  2. タブをフラグメント インスタンスに関連付けることができる。
  3. アクティビティがタブの変更をリスニングできる。

上記の要件を事前に準備することで、抽象化レイヤの範囲を制御できます。それにより、抽象化レイヤの複数の実装を作成する時間が短縮され、下位互換性のある新しい実装をより早く使用できます。

タブの主要な API は ActionBarActionBar.Tab です。これらはタブをバージョン対応にするために抽象化する API です。このサンプル プロジェクトの要件では、Honeycomb(API レベル 11)の新しいタブ機能を利用しつつ、Eclair(API レベル 5)に対する下位互換性を維持することが求められます。この 2 つの実装とその抽象基本クラス(またはインターフェース)をサポートするクラス構造の図を以下に示します。

抽象基本クラスとバージョン固有の実装を含むクラス構造図

図 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();
    ...
}

ここで、インターフェースの代わりに抽象クラスを使用すると、タブ オブジェクトとアクティビティの関連付け(コード スニペットには示されていません)などの一般的な機能を簡単に実装できます。

ActionBar タブメソッドの抽象化

次に、タブを作成して 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 の実装を作成します。

関連ドキュメント