I. Chúng là gì?
1. PagerAdapter
- Là một lớp cơ sở trừu tượng, cung cấp Adapter để điền (content) vào các page bên trong một ViewPager.
- khi chúng ta triển khai (implements) một PagerAdapter, chúng ta phải ghi đè tối thiểu các phương thức sau:
- instantiateItem(ViewGroup container, int position): trả về một Object đại diện cho new page, phương thức này tạo ra một page với vị trí position. Adapter sẽ có trách nhiệm thêm View này vào container (nơi sẽ chứa các page hiển thị), mặc dù vậy, điều này chỉ được đảm bảo thực hiện tại thời điểm nó được trả về từ phương thức finishUpdate(ViewGroup).
- destroyItem(ViewGroup container, int position, Object object): Phương thức này xóa một page với vị trí position. Adapter sẽ có trách nhiệm xóa View này khỏi container, điều này cũng chỉ được đảm bảo thực hiện tại thời điểm nó được trả về từ phương thức finishUpdate(ViewGroup).
- getCount(): phương thức này trả về số lượng View đang có.
- isViewFromObject(View, Object): phương thức này xác định xem một page View có được liên kết với một key object cụ thể nào không (được trả về bởi phương thức instantiateItem ). Đây là phương thức bắt buộc phải có để một PagerAdapter hoạt động bình thường.
- Thêm một vài mô tả chi tiết:
- PagerAdapter tổng quát hơn các adapter được sử dụng cho AdapterViews. Bởi thay vì cung cấp một View theo cơ chế tái chế trực tiếp (View recycling mechanism directly), ViewPager sử dụng các callback để chỉ ra các bước thực hiện trong quá trình cập nhật. Một PagerAdapter có thể triển khai hình thức tái chế View nếu muốn và sử dụng thêm một phương pháp tinh vi trong việc quản lý các page View, chẳng hạn như các FragmentTransaction trong đó mỗi page được trình bày bởi Fragment của chính nó.
- ViewPager liên kết từng page với một key Object thay vì làm việc trực tiếp với các View. Cái key Object này được sử dụng để truy vết và xác định duy nhất một page độc lập với vị trí của nó trong adapter. Khi một lệnh gọi đến phương thức của PagerAdapter là startUpdate(VIewGroup) cho thấy rằng, các nội dung của ViewPager đó sắp thay đổi. Sau đó, một hoặc nhiều các lệnh gọi đến phương thức instantiateItem và (hoặc) destroyItem sẽ diễn ra, sự kết thúc của một hành động cập nhật sẽ được báo hiệu bởi một lệnh gọi đến finishUpdate(ViewGroup). Vào thời điểm finishUpdate trả về các View (các View này được liên kết với các Key Object trả về bởi instantiateItem), chúng phải được thêm vào parent ViewGroup và được chuyển qua phương thức destroyItem để xóa (sau khi chuyển view). Phương thức isViewFromObject xác định liệu một page có được liên kết với Key Object hay không.
- Một PagerAdapter đơn giản có thể chọn sử dụng chính các page View như các Key Object, nó trả về chúng từ phương thức instantiateItem sau khi khởi tạo và thêm chúng vào parent ViewGroup, Một triển khai phương thức destroyItem phù hợp sẽ xóa View ra khỏi parent ViewGroup và phương thức isViewFromObject có thể được triển khai kiểu: return view == object;
- PagerAdapter hỗ trợ thay đổi tập dữ liệu. Việc thay đổi tập dữ liệu phải xảy ra trên luồng chính (main thread) và phải kết thúc với một lệnh gọi đến phương thức notifyDataSetChanged() tương tự như các adapter (AdapterView) bắt nguồn từ android.widget.BaseAdapter. Một thay đổi tập dữ liệu có thể liên quan đến các page được thêm, xóa hoặc thay đổi vị trí. ViewPager có thể giữ page hiện tại hoạt động được cung cấp bởi adapter nhờ triển khai phương thức getItemPosition(Object).
2. FragmentPagerAdapter
- Là một lớp dẫn xuất (lớp con) kế thừa từ lớp PagerAdapter, nó đại diện cho mỗi page như một Fragment và được lưu giữ liên tục trong fragment manager (tạm dịch: trình quản lý fragment) miễn sao người dùng có thể quay lại page với trạng thái page còn nguyên.
- FragmentPagerAdapter là phiên bản tốt nhất sử dụng cho page khi có một số ít các fragment tĩnh thường được phân qua trang, ví dụ như một tập tab. Fragment của mỗi page mà người dùng ghé thăm sẽ được lưu giữ trong bộ nhớ, mặc cho view hierarchy có thể bị hủy khi không được nhìn thấy. Điều này có thể dẫn đến việc sử dụng một lượng bộ nhớ đáng kể khi mà các instance fragment có thể chứa một số lượng trạng thái tùy ý. Đối với tập page lớn hơn, hãy xem xét sử dụng FragmentStatePagerAdapter.
- Khi sử dụng FragmentPagerAdapter, máy chủ ViewPager phải có một tập ID hợp lệ.
- Các lớp con sau khi implements FragmentPagerAdapter chỉ cần triển khai 2 phương thức getItem(int position) và getCount() để có một Adapter làm việc.
- getItem(int position): trả về Fragment được liên kết với một vị trí position được chỉ định.
- getCount(): trả về số lượng View đang có.
- Hiện tại thì:
3. FragmentStatePagerAdapter
- Cũng là một lớp dẫn xuất kế thừa từ lớp PagerAdapter như FragmentPagerAdapter, FragmentStatePagerAdapter sử dụng một Fragment để quản lý từng page, lớp này cũng xử lý việc lưu giữ và khôi phục lại trạng thái của Fragment.
- FragmentStatePagerAdapter là phiên bản tiện ích hơn FragmentPagerAdapter khi nó sử dụng cho một tập chứa số lượng lớn page, có cảm giác nó làm việc giống một List View hơn. Khi các page không hiển thị đến người dùng, toàn bộ Fragment của chúng lúc này có thể bị hủy, chỉ giữ lại trạng thái đã lưu của Fragment. Điều này cho phép pager chiếm ít bộ nhớ hơn nhiều liên quan đến mỗi page đã được truy cập đến so với FragmentPagerAdapter với chi phí (cost) tiềm năng hơn khi chuyển đổi giữa các page.
- Cách sử dụng của FragmentStatePagerAdapter cũng giống với FragmentPagerAdapter.
- Hiện tại thì:
=> Tuy một vài lớp có thể bị khuyến cáo ngừng sử dụng và thay thế bằng các lớp khác, nhưng chúng ta vẫn ngồi đây để tiếp tục tìm hiểu thêm về chúng.
II. Sự khác biệt có thể nhận ra được qua lý thuyết.
-
Trước khi lao vào điểm khác biệt, chúng ta đều nhận ra, từ đầu đến giờ, 3 Adapter này đều liên quan tới ViewPager, Page, … Chúng đều sử dụng trong việc điền (content) vào các page. Lớp PagerAdapter là lớp cha, FragmentPagerAdapter và FragmentStatePagerAdapter là 2 lớp con kế thừa từ lớp PagerAdapter. Có thể nói FragmentPagerAdapter và FragmentStatePagerAdapter kế thừa gần như toàn bộ đặc tính của PagerAdapter, tuy nhiên chúng vẫn có 1 vài điểm khác biệt mà tôi nhận thấy như sau:
-
Điểm khác biệt:
1. PagerAdapter:
+ Cách thức hoạt động phức tạp.
+ Việc giữ hiện trạng hoạt động của page cần phải có sự can thiệp từ người lập trình.2. FragmentPagerAdapter:
+ Fragment được người dùng truy cập đến đều được lưu thẳng vào bộ nhớ, ngay cả khi View bị hủy thì chúng vẫn cứ tồn tại trong bộ nhớ, việc này làm tiêu tốn bộ nhớ và giảm hiệu năng sử dụng của app. ( đặc biệt là khi số lượng page quá nhiều)
+ Trải nghiệm người dùng mượt mà nếu tập page là tập fragment tĩnh với số lượng page không lớn.
+ Nếu dữ liệu trong Fragment thay đổi thì nó sẽ không được cập nhật vì Fragment đã đang được lưu trữ trong bộ nhớ rồi.3. FragmentStatePagerAdapter:
+ Fragment được người dùng truy cập đến thay vì lưu thẳng vào bộ nhớ, lớp này sẽ thực hiện lưu trạng thái của chúng vào bộ nhớ (SaveInstanceState), những Fragment không còn cần nữa đều bị hủy. Điều này có lợi thế trong việc tiết kiệm bộ nhớ.
+ Thích hợp với tập page số lượng lớn với fragment động.
III. Khi nào dùng ?
- Khi bạn có một số lượng Fragment giới hạn và muốn lưu toàn bộ chúng vào bộ nhớ ta dùng FragmentPagerAdapter.
- Khi số lượng fragment là lớn và bạn muốn chúng động ( cập nhật và thay đổi dữ liệu liên tục) ta nên dùng FragmentStatePagerAdapter.
- Các trường hợp còn lại nên quẩy PagerAdapter, ưu tiên những thứ càng đơn giản càng tốt.
Kết:
- Thông qua bài viết này chúng ta có thể nắm thêm 1 chút kiến thức lý thuyết, bài viết lấy nguồn từ Android Developershttps://developer.android.com. Trên đây đều là ý kiến chủ quan của mình, nếu có sai sót các bạn đọc hãy comment cho mình biết nhé. Cảm ơn đã kiên nhẫn đọc bài viết này.
Nguồn: viblo.asia