新しい 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 インターフェースを反映した、タブを表す抽象クラスを作成します。

KotlinJava
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
   
...
}
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() などのアクティビティに追加するための抽象クラスを定義します。

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

   
...
}
public abstract class TabHelper {
   
...

   
public CompatTab newTab(String tag) {
       
// This method is implemented in a later lesson.
   
}

   
public abstract void addTab(CompatTab tab);

   
...
}

次のレッスンでは、新旧両方のプラットフォーム バージョンで動作する TabHelperCompatTab の実装を作成します。

関連ドキュメント