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

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

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

Готовьтесь к абстракции

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

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

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

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

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

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

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

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

Диаграмма классов абстрактных базовых классов и реализаций для конкретных версий.

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

Аннотация ActionBar.Tab

Начните создавать уровень абстракции вкладок, создав абстрактный класс, представляющий вкладку, который отражает интерфейс 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
    ...
}

Ява

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() :

Котлин

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

    ...
}

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

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