Абстрагируйте новые API

Предположим, вы хотите использовать вкладки панели действий в качестве основной формы навигации верхнего уровня в вашем приложении. К сожалению, API ActionBar доступны только в Android 3.0 и более поздних версиях (уровень API 11+). Таким образом, если вы хотите распространять свое приложение на устройствах, работающих под управлением более ранних версий платформы, вам необходимо предоставить реализацию, поддерживающую более новый API, одновременно обеспечивая резервный механизм, использующий более старые API.

В этом уроке вы создадите компонент пользовательского интерфейса с вкладками, использующий абстрактные классы с реализациями, специфичными для каждой версии, для обеспечения обратной совместимости. В этом уроке описывается, как создать слой абстракции для новых API вкладок в качестве первого шага к созданию компонента вкладок.

Подготовьтесь к абстракции

Абстракция в языке программирования Java подразумевает создание одного или нескольких интерфейсов или абстрактных классов для сокрытия деталей реализации. В случае с более новыми API Android можно использовать абстракцию для создания компонентов, учитывающих версии, которые используют текущие API на более новых устройствах и переключаются на более старые, более совместимые API на более старых устройствах.

При использовании этого подхода сначала определяется, какие новые классы вы хотите иметь возможность использовать с сохранением обратной совместимости, а затем создаются абстрактные классы на основе публичных интерфейсов этих новых классов. При определении интерфейсов абстракции следует максимально точно отражать новый API. Это максимизирует обратную совместимость и упрощает удаление уровня абстракции в будущем, когда он больше не потребуется.

После создания абстрактных классов для этих новых API можно создать и выбрать любое количество реализаций во время выполнения. В целях обратной совместимости эти реализации могут различаться в зависимости от требуемого уровня API. Таким образом, одна реализация может использовать недавно выпущенные API, а другие — более старые.

Создайте абстрактный интерфейс вкладок.

Для создания обратно совместимой версии вкладок необходимо сначала определить, какие функции и конкретные API требуются вашему приложению. В случае вкладок верхнего уровня предположим, что у вас есть следующие функциональные требования:

  1. Индикаторы вкладок должны отображать текст и значок.
  2. Вкладки могут быть связаны с экземпляром фрагмента.
  3. Данное приложение должно уметь отслеживать смену вкладок.

Предварительная подготовка этих требований позволяет контролировать область применения вашего уровня абстракции. Это означает, что вы можете потратить меньше времени на создание множества реализаций вашего уровня абстракции и начать использовать новую, обратно совместимую реализацию раньше.

Ключевые API для вкладок находятся в ActionBar и ActionBar.Tab . Именно эти API необходимо абстрагировать, чтобы ваши вкладки учитывали версии. Требования к этому примеру проекта предполагают совместимость с Eclair (уровень API 5) при одновременном использовании новых функций вкладок в Honeycomb (уровень API 11). Ниже приведена диаграмма структуры классов для поддержки этих двух реализаций и их абстрактных базовых классов (или интерфейсов).

Абстрактные базовые классы и реализации, специфичные для каждой версии.
Рисунок 1. Диаграмма классов абстрактных базовых классов и реализаций, специфичных для каждой версии.

Абстрактная панель действий.Вкладка

Начните создавать уровень абстракции для вкладок, разработав абстрактный класс, представляющий вкладку и повторяющий интерфейс ActionBar.Tab :

Котлин

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.newTab() и ActionBar.addTab() :

Котлин

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 , которые будут работать как на старых, так и на новых версиях платформы.

Вам также следует прочитать