Tạo quá trình triển khai với các API cũ

Bài học này thảo luận về cách tạo một quy trình triển khai phản chiếu các API mới hơn nhưng vẫn hỗ trợ các thiết bị cũ.

Quyết định về một giải pháp thay thế

Thách thức lớn nhất khi sử dụng các tính năng giao diện người dùng mới theo cách tương thích ngược là quyết định và triển khai một giải pháp cũ (dự phòng) cho các phiên bản nền tảng cũ. Trong nhiều trường hợp, bạn có thể đáp ứng mục đích của các thành phần giao diện người dùng mới hơn này bằng các tính năng cũ hơn của khung giao diện người dùng. Ví dụ:

  • Bạn có thể triển khai thanh thao tác bằng cách sử dụng LinearLayout ngang chứa các nút hình ảnh, có thể là thanh tiêu đề tuỳ chỉnh hoặc dưới dạng khung hiển thị trong bố cục hoạt động. Bạn có thể trình bày các thao tác bổ sung trong nút Trình đơn của thiết bị.

  • Bạn có thể triển khai các thẻ trên thanh thao tác bằng cách sử dụng một LinearLayout ngang chứa các nút hoặc bằng cách sử dụng phần tử trên giao diện người dùng TabWidget.

  • Bạn có thể triển khai các tiện ích NumberPickerSwitch bằng cách sử dụng các tiện ích SpinnerToggleButton tương ứng.

  • Bạn có thể triển khai tiện ích ListPopupWindowPopupMenu bằng cách sử dụng tiện ích PopupWindow.

Thường thì không có giải pháp chung cho tất cả để điều chỉnh cho phiên bản cũ các thành phần giao diện người dùng mới hơn sang các thiết bị cũ. Lưu ý đến trải nghiệm người dùng: trên các thiết bị cũ, người dùng có thể không quen với các mẫu thiết kế và thành phần giao diện người dùng mới. Hãy suy nghĩ về cách bạn có thể cung cấp chức năng tương tự bằng cách sử dụng các phần tử quen thuộc. Trong nhiều trường hợp, đây không phải là vấn đề lớn – nếu các thành phần giao diện người dùng mới nổi bật trong hệ sinh thái ứng dụng (chẳng hạn như thanh thao tác) hoặc khi mô hình tương tác cơ bản và trực quan (chẳng hạn như chế độ xem vuốt bằng ViewPager).

Triển khai các thẻ bằng các API cũ

Để tạo một chế độ triển khai cũ cho các thẻ trên thanh thao tác, bạn có thể sử dụng TabWidgetTabHost (mặc dù bạn cũng có thể sử dụng các tiện ích Button được bố trí theo chiều ngang). Triển khai việc này trong các lớp có tên là TabHelperEclairCompatTabEclair, vì quá trình triển khai này sử dụng các API được giới thiệu không muộn hơn Android 2.0 (Eclair).

Sơ đồ lớp cho việc triển khai các thẻ Eclair.
Hình 1. Sơ đồ lớp cho việc triển khai các thẻ Eclair.

Quá trình triển khai CompatTabEclair sẽ lưu trữ các thuộc tính của thẻ (chẳng hạn như văn bản và biểu tượng của thẻ) trong các biến thực thể, vì không có đối tượng ActionBar.Tab nào có sẵn để xử lý việc lưu trữ này:

Kotlin

class CompatTabEclair internal constructor(val activity: FragmentActivity, tag: String) :
        CompatTab(tag) {

    // Store these properties in the instance,
    // as there is no ActionBar.Tab object.
    private var text: CharSequence? = null
    ...

    override fun setText(resId: Int): CompatTab {
        // Our older implementation simply stores this
        // information in the object instance.
        text = activity.resources.getText(resId)
        return this
    }

    ...
    // Do the same for other properties (icon, callback, etc.)
}

Java

public class CompatTabEclair extends CompatTab {
    // Store these properties in the instance,
    // as there is no ActionBar.Tab object.
    private CharSequence text;
    ...

    public CompatTab setText(int resId) {
        // Our older implementation simply stores this
        // information in the object instance.
        text = activity.getResources().getText(resId);
        return this;
    }

    ...
    // Do the same for other properties (icon, callback, etc.)
}

Quá trình triển khai TabHelperEclair sử dụng các phương thức trên tiện ích TabHost để tạo các đối tượng TabHost.TabSpec và chỉ báo thẻ:

Kotlin

class TabHelperEclair internal constructor(activity: FragmentActivity) : TabHelper(activity) {

    private var tabHost: TabHost? = null
    ...

    override fun setUp() {
        // Our activity layout for pre-Honeycomb devices
        // must contain a TabHost.
        tabHost = tabHost ?: mActivity.findViewById<TabHost>(android.R.id.tabhost).apply {
            setup()
        }
    }

    override fun addTab(tab: CompatTab) {
        ...
        tabHost?.newTabSpec(tab.tag)?.run {
            setIndicator(tab.getText()) // And optional icon
            ...
            tabHost?.addTab(this)
        }
    }
    // The other important method, newTab() is part of
    // the base implementation.
}

Java

public class TabHelperEclair extends TabHelper {
    private TabHost tabHost;
    ...

    protected void setUp() {
        if (tabHost == null) {
            // Our activity layout for pre-Honeycomb devices
            // must contain a TabHost.
            tabHost = (TabHost) mActivity.findViewById(
                    android.R.id.tabhost);
            tabHost.setup();
        }
    }

    public void addTab(CompatTab tab) {
        ...
        TabSpec spec = tabHost
                .newTabSpec(tag)
                .setIndicator(tab.getText()); // And optional icon
        ...
        tabHost.addTab(spec);
    }

    // The other important method, newTab() is part of
    // the base implementation.
}

Giờ đây, bạn có 2 cách triển khai CompatTabTabHelper: một cách hoạt động trên các thiết bị chạy Android 3.0 trở lên và sử dụng các API mới, còn cách kia hoạt động trên các thiết bị chạy Android 2.0 trở lên và sử dụng các API cũ. Bài học tiếp theo sẽ thảo luận về cách sử dụng những phương thức triển khai này trong ứng dụng của bạn.