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

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

Quyết định giải pháp thay thế

Nhiệm vụ khó khăn nhất trong việc sử dụng các tính năng giao diện người dùng mới hơn theo cách tương thích ngược là quyết định và triển khai giải pháp cũ (dự phòng) cho các phiên bản nền tảng cũ hơn. Trong nhiều trường hợp, bạn có thể thực hiện 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ách sử dụng các tính năng khung giao diện người dùng cũ. 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 khung hiển thị trong bố cục hoạt động. Các thao tác bổ sung có thể hiển thị dưới 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 LinearLayout ngang chứa các nút hoặc dùng thành phầ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 các tiện ích ListPopupWindowPopupMenu bằng các tiện ích PopupWindow.

Thường thì không có giải pháp chung nào đáp ứng được mọi yêu cầu đ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ũ. Hãy chú ý đến trải nghiệm người dùng: trên các thiết bị cũ, người dùng có thể chưa 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 cân nhắc về cách có thể phân phối cùng một chức năng bằng các phần tử quen thuộc. Trong nhiều trường hợp, vấn đề này ít phải được quan tâm – nếu các thành phần giao diện người dùng mới hơn xuất hiện 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ực kỳ đơn giản và trực quan (chẳng hạn như các khung hiển thị vuốt sử dụng ViewPager).

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

Để tạo cách triển khai cũ hơn cho các thẻ thanh thao tác, bạn có thể sử dụng TabWidgetTabHost (mặc dù người dùng có thể sử dụng tiện ích Button được bố trí theo chiều ngang). Hãy triển khai 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 trước phiên bản Android 2.0 (Eclair).

Sơ đồ lớp để triển khai Eclair các thẻ.

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

Quá trình triển khai CompatTabEclair lưu trữ các thuộc tính thẻ như văn bản và biểu tượng thẻ trong các biến thực thể, vì không có đối tượng ActionBar.Tab nào để xử lý bộ nhớ 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.)
}

Việc triển khai TabHelperEclair sử dụng các phương thức trên tiện ích TabHost để tạo đố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.
}

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