Fragment và Activity trong android cơ bản

5/5 - (3 votes)

Kịch bản là một cái activity chứa 2 Fragment MyFragmentWORDMyFragmentKanji. Khi onCreate thì sẽ nhúng MyFragmentWORD vào trước và thằng MyFragmentKanji sẽ được nhúng khi click vào 1 button trên Activity chính.

nguồn trên internet

Trường hợp 1: khi chạy app thì lần lượt các hàm sẽ là:

MainActivity: onCreate
MyFragmentWORD: onAttach
MainActivity: onAttachFragment
MyFragmentWORD: onCreate
MyFragmentWORD: onCreateView
MyFragmentWORD: onActivityCreated
MyFragmentWORD: onStart
MainActivity: onStart
MainActivity: onPostCreate
MainActivity: onResume
MyFragmentWORD: onResume
MainActivity: onResumeFragments
MainActivity: onPostResume

Rút ra kết luận: Chạy onCreate sau đó tạo xong fragment MyFragmentWORD thì chạy tiếp Activity. Song song với điều này nếu muốn đếm có bao nhiêu fragment trong stack thì cần phải kiểm tra ở hàm onResume của Activity nếu không sẽ không đếm được vì lúc ấy chưa tạo xong fragment.

Trường hợp 2: Khi click vào nút và thêm MyFragmentKanji vào sẽ là:

MyFragmentKANJI: onAttach
MainActivity: onAttachFragment
MyFragmentKANJI: onCreate
MyFragmentKANJI: onCreateView
MyFragmentKANJI: onActivityCreated
MyFragmentKANJI: onStart
MyFragmentKANJI: onResume

Nhìn vào log rút ra kết luận khi click thì Activity vẫn đang ở trạng thái onResume, nếu click thì chỉ chạy vòng đời của fragment này MyFragmentKANJI thôi. Và một đều đặc biệt ếu có bất kỳ một fragment được thêm hay thay thế thì sự kiện onAttachFragment của Activity luôn chạy.

Trường hợp 3: Ấn back trở lại thì fragment MyFragmentKANJI sẽ bị remove.

I/MyFragmentKANJI: onPause
I/MyFragmentKANJI: onStop
I/MyFragmentKANJI: onDestroyView
I/MyFragmentKANJI: onDestroy
I/MyFragmentKANJI: onDetach

Trường hợp 4: Khi đã remove MyFragmentKANJI bằng nút Back, sau đó ra màn hình Home thì

MyFragmentWORD: onPause
MainActivity: onPause
MainActivity: onSaveInstanceState Bundle[{data của bundle}}]
MyFragmentWORD: onStop
MainActivity: onStop

Trường hợp 5: Trở lại app từ trường hợp 4

MainActivity: onRestart
MyFragmentWORD: onStart
MainActivity: onStart
MainActivity: onResume
MyFragmentWORD: onResume
MainActivity: onResumeFragments
MainActivity: onPostResume

Trường hợp 6: Khi chưa remove MyFragmentKANJI bằng Back và ra màn hình Home thì

MyFragmentWORD: onPause
MyFragmentKANJI: onPause
MainActivity: onPause
MainActivity: onSaveInstanceState Bundle[{[{Bundle có data}]
MyFragmentWORD: onStop
MyFragmentKANJI: onStop
MainActivity: onStop

Kết luận: dừng lần lượt các fragment (tùy vào cái nào được thêm vào trước thì dùng trước). Và stop Activity.

Trường hợp 7: Tiếp trường hợp 6 sau khi ra màn hình Home và mở lại app

MainActivity: onRestart
MyFragmentWORD: onStart
MyFragmentKANJI: onStart
MainActivity: onStart
MainActivity: onResume
MyFragmentWORD: onResume
MyFragmentKANJI: onResume
MainActivity: onResumeFragments
MainActivity: onPostResume

Kết luận: Khởi động sự kện onStart của Activity trước sau đó mới gắn Fragment lên Activity.

Bonus:

Khi Activity được tạo thì gắn ồng thời 2 Fragment vào mà không ần click để MyFragmentKANJI hiện lên nữa. Kết  quả như sau:

MainActivity: onCreate

MyFragmentWORD: onAttach
MainActivity: onAttachFragment
MyFragmentWORD: onCreate
MyFragmentWORD: onCreateView
MyFragmentWORD: onActivityCreated

MyFragmentKANJI: onAttach
MainActivity: onAttachFragment
MyFragmentKANJI: onCreate
MyFragmentKANJI: onCreateView
MyFragmentKANJI: onActivityCreated

MyFragmentWORD: onStart
MyFragmentKANJI: onStart
MainActivity: onStart
MainActivity: onPostCreate
MainActivity: onResume:
MyFragmentWORD: onResume
MyFragmentKANJI: onResume
MainActivity: onResumeFragments
MainActivity: onPostResume

NOTE QUAN TRỌNG

  • Nếu dùng add() Fragment B và dùng addToBackStack() thì Fragment B hiện đè lên Fragment A, nếu B trong suốt thì có thể thấy A bên dưới và khi ấn nút Back thì B bị destroy và để lộ ra Fragment A (Vì Fragment này còn nguyên trên View và trong BackStack chưa bị hủy).

  • Nếu dùng add() Fragment B mà không dùng addToBackStack() thì Fragment B hiện đè lên Fragment A, nếu B trong suốt thì có thể thấy A bên dưới. Nhưng ấn nút Back thì sẽ destroy luôn cả Activity vì bây giờ BackStack không có fragment nào(Lúc gán A lên Activity ở onCreate() cũng không dùng addToBackStack).

  • Nếu dùng replace() Fragment A bằng Fragment B có dùng addToBackStack() thì View A bị xóa khỏi View, View B hiện lên và thêm A vào BackStack. Do đó khi ấn nút Back thì hủy Fragment B sau đó lấy từ BackStack ra Fragment A và hiện A lên View.

  • Nếu dùng replace() Fragment A mà không addToBackStack() thì Fragment B hiện lên, Fragment A bị xóa khỏi View và bị destroy, ấn nút Back thì sẽ destroy luôn cả Activity vì bây giờ BackStack không có fragment nào (Lúc gán A lên Activity ở onCreate() cũng không dùng addToBackStack).

  • Chú ý 1: addBackToStack để lưu trạng thái trước nó chứ không phải nó. ví dụ code này sẽ lưu trạng thái của cái container chứ không lưu trạng thái của fragment SearchWord. Để lưu trạng thái Fragment SearchWord thì cần addToBackStack ở câu lệnh replace hoặc add tiếp theo.

  FragmentTransaction transaction = fragmentManager.beginTransaction();
        transaction.add(R.id.container, new SearchWord(), "SearchWord").addToBackStack(null);
        transaction.commit();
  • Có thể dùng popBackStack() để xóa 1 fragment ra khỏi stack một cách không đồng bộ.

  • Khi muốn lưu trạng thái của Fragment thì sẽ tến hành lưu ở onPause và restore lại ở onStart().

– onSaveInstanceState() chỉ dùng để lưu trạng thái khi cấu hình thay đổi như xoay màn hình chẳng hạn.

Bài tập và đáp án:

Mình muốn bạn code và chạy thử rồi sau đó nộp bài tại đây. Các câu hỏi này được trích ra từ training file của công ty NTQ Solution Android Development.


1) Vẽ lại lifecyle của Fragment.

2) Vẽ lại diagram mô tả vòng đời của Activity và Fragment cùng nhau. Diagram thể hiện được mối liên kết giữa lifecyle của Activity và lifecyle của Fragment.

Ví dụ: Khi Activity ở trạng thái Created thì callback nào (trạng thái nào) của Fragment được gọi, tương tự cho: Started, Resumed …

3) Cách giao tiếp của Fragment với Activity? Viết demo. (gợi ý thông qua hàm callback và chúng ta sẽ dùng Interface)

4) Viết demo Fragment A truyền data cho Fragment B, Fragment B xử lý xong truyền ngược lại kết quả cho Fragment A. (Gợi ý: dùng setTargetFragment(…) và check onActivityResult() của Fragment)

5) Sử dụng onSaveInstance() trong Fragment. Khi restore data đã save ở onSaveInstance() thì nên restore data đó ở đâu? (onCreate, onCreateView, onActivityCreated …)

6) Trình bày sự khác nhau giữa: replace(), add() của FragmentTransaction?

7) addToBackStack () method của FragmentTransaction dùng làm gì? Vẽ hình mô tả.

8) popBackStack() method của FragmentManager dùng làm gì?

CHECKOUT SOURCE

Các bài viết không xem thì tiếc:

Thảo luận

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Xem thêm
Khi dùng git chắc chắn ai cũng gặp trường hợp…
 
 
 
 
Facetime iPhone

Main Menu