Giới thiệu Fragment trong Android

Fragment cho phép phân chia Activity thành các thành phần được đóng gói đầy đủ và tái sử dụng được. Các Fragment có vòng đời và giao diện UI riêng của mình.

Ưu điểm chính của Fragment là dễ dàng tạo ra thiết kế giao diện người dùng (UI) động và linh hoạt, phù hợp với các kích cỡ màn hình khác nhau từ màn hình nhỏ trên điện thoại thông minh đến kích thước màn hình máy tính bảng.

Mỗi Fragment là một module độc lập có ràng buộc chặt chẽ vào Activity mà nó gắn vào. Fragment có thể được tái sử dụng trong nhiều Activity, và trong một activity có thể được gắn vào nhiều Fragment.

Fragment cung cấp cách để trình bày giao diện người dùng (UI) phù hợp và tối ưu cho các loại thiết bị Android có kích thước màn hình và mật độ điểm ảnh khác nhau.

Fragment được giới thiệu trong phiên bản Android 3.0 Honeycomb (API level 11).

Tạo một Fragment

Extend lớp Fragment để tạo một fragment mới, có thể định nghĩa UI và implement các chức năng đóng gói của nó.

Trong hầu hết các trường hợp, bạn sẽ muốn chỉ định UI cho fragment. Tuy nhiên, bạn cũng có thể sử dụng một fragment để cung cấp một hành vi chạy ngầm cho hoạt động mà không cần đưa UI bổ sung.

Để cung cấp một layout cho một fragment, phải triển khai phương thức gọi lại onCreateView(), phương thức này được hệ thống Android gọi khi đến khi fragment vẽ layout của nó. Việc triển khai phương thức này phải trả về một View là phần gốc cho layout của fragment.

    public class MySkeletonFragment extends Fragment {
        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
            // Create, or inflate the Fragment’s UI, and return it.
            // If this Fragment has no UI then return null.
            return inflater.inflate(R.layout.my_fragment, container, false);
        }
    }

Vòng đời của fragment

Việc quản lý vòng đời của một fragment rất giống với quản lý vòng đời của một activity. Tuy nhiên, vòng đời của fragment chịu ảnh hưởng bởi vòng đời của activity mà nó gắn vào. Chỉ khi activity ở trạng thái resumed thì vòng đời của fragment mới có thể thay đổi độc lập.

fragment_lifecycle.png

Attach và Detach fragment từ Activity

Vòng đời đầy đủ của fragment được bắt đầu khi nó được gắn với Activity cha và kết thúc khi nó được tách ra. Những sự kiện này tương ứng với những phương thức gọi lại onAttach()onDetach().

    // Called when the Fragment is attached to its parent Activity.
    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);
        // Get a reference to the parent Activity.
    }

    // Called when the Fragment has been detached from its parent Activity.
    @Override
    public void onDetach() {
        super.onDetach();
    }

Create và Destroy fragment

Cũng như Activity, bạn có thể sử dụng phương thức onCreate() để khởi tạo fragment. Đây cũng là vị trí tốt để tạo các đối tượng trong phạm vi class để đảm bảo chúng chỉ được tạo ra chỉ một lần trong vòng đời fragment.

Chú ý: Không giống như Activity, giao diện UI của fragment không được khởi tạo bên trong onCreate()

     // Called to do the initial creation of the Fragment.
     @Override
     public void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
         // Initialize the Fragment.
     }

     // Called at the end of the full lifetime.
     @Override
     public void onDestroy() {
         // Clean up any resources including ending threads,
         // closing database connections etc.
         super.onDestroy();
     }

Create và Destroy giao diện người dùng (User Interface)

Giao diện người dùng(UI) của fragment được khởi tạo (và huỷ) tương ứng với với việc xử lý sự kiện trong phương thức onCreateView()onDestroyView().

    // Called once the Fragment has been created in order for it to
    // create its user interface.
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        // Create, or inflate the Fragment’s UI, and return it.
        // If this Fragment has no UI then return null.
        return inflater.inflate(R.layout.my_fragment, container, false);
    }

    // Called when the Fragment’s View has been detached.
    @Override
    public void onDestroyView() {
        // Clean up resources related to the View.
        super.onDestroyView();
    }

Quản lý fragment

Mỗi Activity có một Fragment Manager để quản lý các fragment bên trong nó. Để có nó, sử dụng phương thức getFragmentManager():

     FragmentManager fragmentManager = getFragmentManager();

Fragment Manager cung cấp các phương thức sử dụng để truy cập vào fragment hiện tại đã được gắn vào Activity và thực hiện các giao tác fragment để thêm, xoá hay thay thế fragment.

Một tính năng tuyệt vời khi sử dụng fragment trong Activity đó là khả năng thêm, gỡ bỏ, thay thế, và thực hiện các hành động khác với chúng, để hồi đáp lại tương tác của người dùng. Mỗi tập hợp thay đổi mà bạn thực thi cho Activity được gọi là một giao tác và bạn có thể thực hiện một giao tác bằng cách sử dụng các API trong FragmentTransaction. Bạn cũng có thể lưu từng giao tác vào một ngăn xếp được quản lý bởi Activity, cho phép người dùng điều hướng ngược lại thông qua những thay đổi fragment (tương tự như điều hướng ngược lại thông qua Activity).

Bạn có thể thu được một thực thể của FragmentTransaction từ FragmentManager như sau:

     FragmentManager fragmentManager = getFragmentManager();
     FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();

Mỗi giao tác là một tập hợp những thay đổi mà bạn muốn thực hiện tại cùng thời điểm. Bạn có thể thiết lập tất cả thay đổi mà mình muốn thực hiện đối với một giao tác cho trước bằng cách sử dụng các phương pháp như add(), remove(), và replace(). Sau đó, để áp dụng giao tác cho Activity, bạn phải gọi commit().

Trước khi bạn gọi commit(), bạn có thể muốn gọi addToBackStack(), để thêm giao tác vào một ngăn xếp của các giao tác fragment. Ngăn xếp này được quản lý bởi Activity và cho phép người dùng trở về trạng thái fragment trước đó, bằng cách nhấp nút Quay lại.

     FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
     fragmentTransaction.add(R.id.ui_container, new MyListFragment());
     Fragment fragment = fragmentManager.findFragmentById(R.id.details_fragment);
     fragmentTransaction.remove(fragment);
     String tag = null;
     fragmentTransaction.addToBackStack(tag);
     fragmentTransaction.commit();

Giao diện giữa Fragment và Activity

Trong một số trường hợp, bạn có thể cần một fragment để chia sẻ sự kiện với Activity. Một cách hay để làm điều này đó là định nghĩa một giao diện gọi lại bên trong fragment và yêu cầu Activity cha triển khai nó. Khi Activity nhận được một lệnh gọi lại thông qua giao diện, nó có thể chia sẻ thông tin với các fragment khác nếu cần.

     public interface OnSeasonSelectedListener {
         public void onSeasonSelected(Season season);
    }

    private OnSeasonSelectedListener onSeasonSelectedListener;
    private Season currentSeason;

    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);
        try {
            onSeasonSelectedListener = (OnSeasonSelectedListener)activity;
        } catch (ClassCastException e) {
            throw new ClassCastException(activity.toString() +
            “ must implement OnSeasonSelectedListener”);
        }
    }

    private void setSeason(Season season) {
        currentSeason = season;
        onSeasonSelectedListener.onSeasonSelected(season);
    }

Các class Fragment trong Android

Android SDK cung cấp một số lớp con của Fragment:

  • DialogFragment: Hiển thị một hộp thoại trôi nổi. Sử dụng lớp này để tạo một hộp thoại là một phương án hay cho việc sử dụng các phương pháp trình trợ giúp hộp thoại trong lớp Activity, vì bạn có thể kết hợp một hộp thoại fragment vào ngăn xếp của các fragment được quản lý bởi Activity, cho phép người dùng trả về một fragment bị bỏ.
  • ListFragment: Hiển thị một danh sách các mục được quản lý bởi một trình điều hợp (chẳng hạn như một SimpleCursorAdapter), tương tự như ListActivity. Nó cung cấp một vài phương pháp để quản lý một dạng xem danh sách, chẳng hạn như phương pháp gọi lại onListItemClick() để xử lý các sự kiện nhấp.
  • PreferenceFragment: Hiển thị một phân cấp các đối tượng Preference dưới dạng một danh sách, tương tự như PreferenceActivity. Điều này hữu ích khi tạo một Activity "setting" cho ứng dụng của bạn.