Omówienie nowych interfejsów API

Załóżmy, że chcesz jako podstawowej formy nawigacji najwyższego poziomu w aplikacji używać kart na pasku działań. Interfejsy API ActionBar są dostępne tylko w Androidzie 3.0 lub nowszym (poziom API 11 lub nowszy). Jeśli więc chcesz dystrybuować swoją aplikację na urządzeniach z wcześniejszymi wersjami platformy, musisz zapewnić implementację, która obsługuje nowszy interfejs API, a jednocześnie udostępnienie mechanizmu zastępczego korzystającego ze starszych interfejsów API.

W ramach tych zajęć utworzysz komponent interfejsu z kartami, który korzysta z klas abstrakcyjnych i z implementacjami specyficznymi dla danej wersji, aby zapewnić zgodność wsteczną. Z tej lekcji dowiesz się, jak utworzyć warstwę abstrakcji dla interfejsów API nowych kart. Jest to pierwszy krok do utworzenia komponentu karty.

Przygotuj się do abstrakcji

Abstrakcja w języku programowania Java polega na utworzeniu co najmniej jednego interfejsu lub klas abstrakcyjnych w celu ukrycia szczegółów implementacji. W przypadku nowszych interfejsów API Androida możesz użyć abstrakcji, aby tworzyć komponenty zorientowane na wersję, które korzystają z bieżących interfejsów API na nowszych urządzeniach, lub korzystać ze starszych, bardziej zgodnych interfejsów API na starszych urządzeniach.

W przypadku tej metody najpierw musisz określić, których nowszych klas można używać w sposób zgodny wstecznie, a potem utworzyć klasy abstrakcyjne na podstawie publicznych interfejsów nowych klas. Definiując interfejsy abstrakcji, w miarę możliwości powielaj nowszy interfejs API. Zwiększa to zgodność do przodu i ułatwia usunięcie warstwy abstrakcji w przyszłości, gdy nie jest już potrzebna.

Po utworzeniu klas abstrakcyjnych dla nowych interfejsów API można utworzyć i wybrać dowolną liczbę implementacji w czasie działania. Ze względu na zgodność wsteczną wdrożenia mogą się różnić w zależności od wymaganego poziomu interfejsu API. Oznacza to, że w jednej implementacji mogą być używane ostatnio opublikowane interfejsy API, a inne – starsze.

Utwórz abstrakcyjny interfejs karty

Aby utworzyć wersję kart zgodną wstecznie, musisz najpierw określić, których funkcji i interfejsów API potrzebuje Twoja aplikacja. W przypadku kart sekcji najwyższego poziomu załóżmy, że spełnione są następujące wymagania funkcjonalne:

  1. Wskaźniki kart powinny zawierać tekst i ikonę.
  2. Karty mogą być powiązane z instancją fragmentu.
  3. Aktywność powinna wykrywać zmiany na karcie.

Przygotowanie tych wymagań z wyprzedzeniem pozwoli Ci kontrolować zakres warstwy abstrakcji. Oznacza to, że możesz poświęcać mniej czasu na tworzenie wielu implementacji warstwy abstrakcji i szybciej zacząć korzystać z nowej implementacji, która jest zgodna wstecznie.

Kluczowe interfejsy API dla kart znajdują się w językach ActionBar i ActionBar.Tab. To są interfejsy API, które należy wyodrębnić, aby uwzględniać wersje kart. Wymagania tego przykładowego projektu wymagają ponownej zgodności z technologią Eclair (poziom interfejsu API 5), a jednocześnie korzystanie z nowych funkcji kart w Honeycomb (poziom API 11). Poniżej znajduje się schemat struktury klas obsługującej te 2 implementacje oraz ich abstrakcyjne klasy podstawowe (lub interfejsy).

Diagram abstrakcyjnych klas podstawowych i implementacji zależnych od wersji.

Rysunek 1. Diagram abstrakcyjnych klas podstawowych i implementacji zależnych od wersji.

Abstrakcyjny pasek akcji.Tab

Zacznij tworzyć warstwę abstrakcji kart, tworząc klasę abstrakcyjną reprezentującą kartę, która odzwierciedla interfejs 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();
    ...
}

Zamiast interfejsu możesz użyć klasy abstrakcyjnej, aby uprościć implementację typowych funkcji, takich jak powiązanie obiektów karty z działaniami (niewidocznych we fragmencie kodu).

Abstrakcyjne metody karty ActionBar

Następnie zdefiniuj klasę abstrakcyjną, która umożliwia tworzenie kart i dodawanie do nich kart, np. ActionBar.newTab() i 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);

    ...
}

W kolejnych lekcjach utworzysz implementacje dla TabHelper i CompatTab, które działają zarówno w starszych, jak i nowszych wersjach platformy.

Warto też przeczytać