新しい 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 の実装を作成します。

関連ドキュメント