Абстрагирование новых 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. Диаграмма классов абстрактных базовых классов и реализаций для конкретных версий.

Abstract 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

Затем определите абстрактный класс, который позволяет создавать и добавлять вкладки в объект 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);

    ...
}

На следующих уроках вы создадите реализации для TabHelper и CompatTab, которые будут работать как в старых, так и в новых версиях платформы.

Также рекомендуем ознакомиться со следующими материалами: