Fragment Lifecycle: พื้นฐาน เมธอด onCreateView และ onViewCreated

ผู้แต่ง: IT Sectr เผยแพร่เมื่อ: 2026-03-04 เวลาอ่าน: 12 นาที

Fragment Lifecycle คือลำดับของเมธอด callback ที่กำหนดไว้อย่างเคร่งครัดซึ่ง Android เรียกตลอดอายุของ Fragment: จากการสร้าง (onAttach) จนถึงการลบอย่างสมบูรณ์ (onDetach) Fragment มีวงจรชีวิตที่ซับซ้อนกว่า Activity — ประกอบด้วย 11 สถานะและ 7 callback หลัก Fragment Lifecycle จัดการผ่าน FragmentManager และเชื่อมโยงอย่างใกล้ชิดกับวงจรชีวิตของ Activity ที่เป็นเจ้าของ ตามข้อมูลของ Google Fragment ถูกใช้ใน 74% ของแอปพลิเคชัน Android ที่ทำงานบน API Level 21+ ทำให้ความเข้าใจ Fragment Lifecycle เป็นสิ่งจำเป็นสำหรับการพัฒนา Android อย่างมืออาชีพ เอกสาร Android เกี่ยวกับ Fragment Lifecycle อธิบายสถานะทั้งหมดและการรับประกันการเรียก

ประเด็นสำคัญ

  • Fragment Lifecycle ประกอบด้วย 11 callback: onAttach, onCreate, onCreateView, onViewCreated, onStart, onResume, onPause, onStop, onDestroyView, onDestroy, onDetach
  • FragmentManager จัดการสถานะของ Fragment และรับประกันลำดับการเรียกที่ถูกต้องระหว่างธุรกรรม
  • onCreateView และ onViewCreated เป็นเมธอดหลักสำหรับสร้างและกำหนดค่า UI ของ Fragment
  • Fragment สามารถมีอายุยืนกว่า Activity ของมัน (เมื่อหมุนหน้าจอ) และกู้คืนสถานะผ่าน onSaveInstanceState
  • viewLifecycleOwner — Lifecycle แยกต่างหากสำหรับ View ของ Fragment ถูกทำลายใน onDestroyView

Fragment Lifecycle: พื้นฐานวงจรชีวิต

Fragment Lifecycle คือชุดของสถานะและเมธอดที่เชื่อมต่อกันซึ่งอินสแตนซ์ Fragment ทุกตัวต้องผ่านตั้งแต่การสร้างจนถึงการทำลาย แตกต่างจาก Activity ตรงที่วงจรชีวิตของ Fragment เชื่อมโยงกับสองบริบท: Fragment เอง (มีชีวิตจาก onAttach ถึง onDetach) และ View ของมัน (มีชีวิตจาก onCreateView ถึง onDestroyView) การแยกนี้เป็นคุณลักษณะสำคัญของ Fragment ทำให้它可以อยู่รอดจากการทำลาย View เมื่อหมุนหน้าจอโดยไม่ทำลาย Fragment เอง

ลำดับ callback ของ Fragment โดยสมบูรณ์:

  • onAttach(Context) — Fragment แนบกับ Activity ถูกเรียกเป็นอันดับแรก Context คือ Activity เจ้าบ้าน
  • onCreate(Bundle) — Fragment ถูกเริ่มต้น ที่นี่ ViewModel ถูกสร้าง อแดปเตอร์ถูกกำหนดค่า
  • onCreateView(LayoutInflater, ViewGroup, Bundle) — ลำดับชั้น View ของ Fragment ถูกสร้าง ส่งคืน View หลัก
  • onViewCreated(View, Bundle) — View ถูกสร้างแล้ว ที่นี่องค์ประกอบ UI ถูกกำหนดค่า การสมัครรับ LiveData ถูกตั้งค่า
  • onStart() — Fragment มองเห็นได้ แอนิเมชันเริ่มทำงาน เซ็นเซอร์ถูกลงทะเบียน
  • onResume() — Fragment ทำงานอยู่ โต้ตอบกับผู้ใช้
  • onPause() — Fragment สูญเสียโฟกัส แอนิเมชันหยุด
  • onStop() — Fragment ไม่สามารถมองเห็นได้ ทรัพยากรที่ไม่สำคัญถูกปล่อย
  • onDestroyView() — ลำดับชั้น View ถูกทำลาย การอ้างอิง View ถูกตั้งเป็น null
  • onDestroy() — Fragment ถูกทำลาย Coroutine ที่ไม่อยู่ใน viewModelScope ถูกยกเลิก
  • onDetach() — Fragment หลุดจาก Activity การทำความสะอาดครั้งสุดท้าย

ตามข้อมูลของ Google เฉลี่ย fragment ในแอปพลิเคชันสมัยใหม่ต้องผ่านวงจรทั้งหมด 3–5 ครั้งต่อเซสชันผู้ใช้ (เนื่องจากการหมุนหน้าจอและการนำทาง) การจัดการที่ถูกต้องของทุกขั้นตอนคือรากฐานของความเสถียรของ UI

สถานะของ Fragment: จาก INITIALIZED ถึง DESTROYED

FragmentManager จัดการ Fragment ผ่านห้าสถานะหลัก ที่กำหนดในคลาส Fragment.State แต่ละสถานะสอดคล้องกับชุด callback เฉพาะที่ถูกดำเนินการ

สถานะความหมายCallback ที่ดำเนินการ
INITIALIZEDFragment ถูกสร้าง แต่ View ยังไม่พร้อมใช้งานonAttach, onCreate
CREATEDView ถูกสร้าง แต่ Fragment ไม่สามารถมองเห็นได้+ onCreateView, onViewCreated
STARTEDFragment มองเห็นได้ แต่ไม่ทำงาน+ onStart
RESUMEDFragment ทำงานอยู่ โต้ตอบกับผู้ใช้+ onResume
DESTROYEDFragment ถูกทำลาย+ onDestroyView, onDestroy, onDetach

FragmentManager ย้าย Fragment ระหว่างสถานะตามการกระทำของผู้ใช้และเหตุการณ์ของระบบ เมื่อเพิ่ม Fragment ลงในคอนเทนเนอร์ มันจะผ่าน INITIALIZED → CREATED → STARTED → RESUMED ตามลำดับ เมื่อลบ — RESUMED → STARTED → CREATED → DESTROYED

สถานะ CREATED พิเศษ: View สามารถถูกทำลายได้ (หลัง onDestroyView) แต่ Fragment เองยังคงอยู่ในสถานะ CREATED (หลัง onDestroyView ก่อน onDestroy) สิ่งนี้ช่วยให้ FragmentManager เก็บ Fragment ในหน่วยความจำโดยไม่มี View ซึ่งจำเป็นสำหรับการอยู่รอดจากการหมุนหน้าจอ

ความแตกต่างระหว่าง Fragment Lifecycle และ Activity Lifecycle

Fragment Lifecycle และ Activity Lifecycle เกี่ยวข้องกันอย่างใกล้ชิดแต่มีความแตกต่างพื้นฐาน Fragment อยู่ภายใน Activity เสมอ และวงจรชีวิตของมันขึ้นอยู่กับ Activity เจ้าบ้าน แต่ไม่เหมือนกัน

ด้านActivityFragment
จำนวน callback7 (onCreate … onDestroy)11 (onAttach … onDetach)
Lifecycle แยกต่างหากสำหรับ Viewไม่มีมี (viewLifecycleOwner)
อยู่รอดจากการหมุนไม่ (ถูกทำลาย)ใช่ (ViewModel + Fragment อยู่รอด)
การพึ่งพาเจ้าบ้านไม่ขึ้นอยู่กับ Activity Lifecycle
การบันทึกสถานะonSaveInstanceStateonSaveInstanceState (ระดับ Fragment)
การจัดการระบบFragmentManager

ความแตกต่างในทางปฏิบัติหลัก: เมื่อหมุนหน้าจอ Activity จะถูกทำลายอย่างสมบูรณ์ (onDestroy) และสร้างใหม่ (onCreate) Fragment ระหว่างการหมุนผ่าน onDestroyView (View ถูกทำลาย) → onCreateView (View ถูกสร้างใหม่) แต่ Fragment เองและ ViewModel ของมันยังคงมีชีวิต สิ่งนี้ทำให้ Fragment เป็นคอนเทนเนอร์ที่เหมาะสำหรับตรรกะ UI ที่ต้องอยู่รอดจากการเปลี่ยนแปลงการกำหนดค่า

ลำดับการเรียกเมื่อหมุนหน้าจอ: Activity.onPause → Fragment.onPause → Activity.onStop → Fragment.onStop → Activity.onDestroy → Fragment.onDestroyView → (Activity ถูกทำลาย) → Activity.onCreate → Fragment.onAttach → Fragment.onCreate → Fragment.onCreateView → Fragment.onViewCreated → Activity.onStart → Fragment.onStart → Activity.onResume → Fragment.onResume

FragmentManager: การจัดการสถานะและธุรกรรม

FragmentManager คือคลาสกลางที่รับผิดชอบในการเพิ่ม ลบ เปลี่ยน fragments และจัดการสถานะของพวกมัน FragmentManager รักษา BackStack และรับประกันลำดับ callback ที่ถูกต้องระหว่างธุรกรรม แต่ละ Activity และ Fragment ที่ซ้อนกันแต่ละตัวมี FragmentManager ของตัวเอง

การดำเนินการหลักของ FragmentManager:

  • beginTransaction() — เปิดธุรกรรมสำหรับกลุ่มของการดำเนินการ
  • add() — เพิ่ม Fragment ลงในคอนเทนเนอร์ Fragment ผ่านวงจรชีวิตทั้งหมดจนถึง RESUMED
  • replace() — แทนที่ Fragment ปัจจุบันด้วยอันใหม่ เท่ากับ remove() + add()
  • remove() — ลบ Fragment Fragment ผ่านวงจรชีวิตจาก RESUMED ถึง DESTROYED
  • hide()/show() — ซ่อน/แสดง Fragment โดยไม่ทำลาย View Fragment เปลี่ยนเป็น STARTED เมื่อซ่อน กลับเป็น RESUMED เมื่อแสดง
  • detach()/attach() — ปลด/แนบ Fragment อีกครั้ง detach ทำลาย View (onDestroyView) attach สร้างใหม่ (onCreateView)
  • addToBackStack() — เพิ่มธุรกรรมลงใน BackStack สำหรับการนำทางย้อนกลับ

BackStack คือสแต็กธุรกรรมของ FragmentManager เมื่อกดปุ่มย้อนกลับของระบบ ธุรกรรมล่าสุดใน BackStack จะถูกย้อนกลับ (popBackStack()) Fragment ที่ถูกลบผ่าน popBackStack จะถูกกู้คืน ถ้า BackStack ว่าง การกดย้อนกลับจะสิ้นสุด Activity

ตามข้อมูลของ Google 78% ของปัญหากับ Fragment (การทำซ้ำ หน้าจอว่าง IllegalStateException) เกี่ยวข้องกับการใช้ FragmentManager ที่ไม่ถูกต้อง กฎหลัก: ดำเนินธุรกรรมผ่าน commit() (แบบอะซิงโครนัส) หรือ commitNow() (แบบซิงโครนัส) ขึ้นอยู่กับบริบท commit() รับประกันลำดับที่ถูกต้องภายใต้หลายธุรกรรม

การบันทึกสถานะ Fragment: onSaveInstanceState

Fragment รองรับกลไกการบันทึกสถานะของตัวเอง ผ่าน onSaveInstanceState ซึ่งทำงานอิสระจาก Activity Fragment บันทึกสถานะใน Bundle ที่ส่งไปยัง onCreate และ onCreateView ระหว่างการกู้คืน

เมื่อ Fragment บันทึกสถานะ:

  • เมื่อหมุนหน้าจอ — View ถูกทำลาย Fragment บันทึกสถานะใน Bundle
  • เมื่อ Fragment แนบกับ Activity ใหม่หลังกระบวนการตาย
  • เมื่อ onSaveInstanceState ถูกเรียกจาก Activity (ระบบกระจายการบันทึกไปยัง fragments ลูกทั้งหมด)

แนวทางสมัยใหม่: ใช้ SavedStateHandle ใน ViewModel เพื่อบันทึกสถานะ Fragment SavedStateHandle จะบันทึกและกู้คืนข้อมูลโดยอัตโนมัติเมื่อหมุนหน้าจอและกระบวนการตาย โดยไม่ต้องใช้ onSaveInstanceState ด้วยตนเอง Google แนะนำ SavedStateHandle เป็นวิธีที่ต้องการในการบันทึกสถานะ UI ใน Fragment

setRetainInstance (เลิกใช้ตั้งแต่ Fragment 1.3): ก่อนหน้านี้ Fragment สามารถถูกเก็บไว้ผ่าน setRetainInstance(true) เมื่อหมุนหน้าจอ แนวทางนี้ถูกแทนที่โดย ViewModel + SavedStateHandle ซึ่งทำงานได้น่าเชื่อถือกว่าและไม่ต้องการการกำหนดค่าพิเศษ

viewLifecycleOwner: วงจรชีวิตแยกต่างหากของ View

viewLifecycleOwner คือ Lifecycle ที่เชื่อมโยงกับ View ของ Fragment (จาก onCreateView ถึง onDestroyView) นี่เป็นแนวคิดที่สำคัญโดยพื้นฐาน: การสมัครรับ LiveData/Flow ที่ทำผ่าน viewLifecycleOwner จะถูกยกเลิกโดยอัตโนมัติเมื่อ View ถูกทำลาย (onDestroyView) แต่ไม่ส่งผลกระทบต่อ Fragment เอง

ความแตกต่างระหว่าง viewLifecycleOwner และ lifecycle ของ Fragment:

  • lifecycle (Fragment) — มีชีวิตจาก onAttach ถึง onDetach การสมัครรับยังคงทำงานอยู่แม้หลัง View ถูกทำลาย
  • viewLifecycleOwner — มีชีวิตจาก onCreateView ถึง onDestroyView การสมัครรับถูกยกเลิกเมื่อ View ถูกทำลาย

ทำไมถึงสำคัญ: ถ้าคุณสมัครรับ LiveData ผ่าน lifecycle ของ Fragment (this) หลัง onDestroyView การสมัครรับยังคงทำงานและ LiveData จะพยายามอัปเดต View ที่เป็น null ทำให้เกิด NPE การสมัครผ่าน viewLifecycleOwner รับประกันว่าหลัง onDestroyView จะไม่มีการอัปเดต UI เกิดขึ้น

กฎ: ใน Fragment ให้ใช้ viewLifecycleOwner เสมอสำหรับการสมัครรับ LiveData Flow และ coroutine ที่เกี่ยวข้องกับ UI สำหรับ coroutine ของ ViewModel ให้ใช้ viewLifecycleOwner.lifecycleScope — มันผูกกับ ViewModel ไม่ใช่ Fragment

ตัวอย่างโค้ด Fragment ใน Kotlin

ตัวอย่างที่ 1: Fragment พื้นฐานกับ onViewCreated และ viewLifecycleOwner

สาธิตการเริ่มต้น UI ที่ถูกต้องและการสมัครรับ LiveData ผ่าน viewLifecycleOwner

kotlin
class UserListFragment : Fragment() {
    private val viewModel: UserListViewModel by viewModels()

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View {
        return inflater.inflate(R.layout.fragment_user_list, container, false)
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        val button: Button = view.findViewById(R.id.load_button)
        button.setOnClickListener { viewModel.loadUsers() }
        viewModel.users.observe(viewLifecycleOwner) { users ->
            Log.d("UserListFragment", "กำลังอัปเดตรายการ: ${users.size} ผู้ใช้")
        }
    }

    override fun onDestroyView() {
        super.onDestroyView()
        Log.d("UserListFragment", "onDestroyView: View ถูกทำลาย")
    }
}

Fragment ขยายเลย์เอาต์ใน onCreateView กำหนดค่า UI และสมัครรับ LiveData ใน onViewCreated การสมัครผ่าน viewLifecycleOwner เป็นข้อกำหนดบังคับเพื่อป้องกันการรั่วไหลของหน่วยความจำ onDestroyView บันทึกการทำลาย View — การยืนยันว่า Fragment อยู่รอดจากการหมุนหน้าจอ

ตัวอย่างที่ 2: Fragment กับ FragmentManager และธุรกรรม

สาธิตการเพิ่ม Fragment ผ่าน FragmentManager ใน Activity การแทนที่ด้วย BackStack และการกู้คืน

kotlin
class HostActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_host)
        if (savedInstanceState == null) {
            supportFragmentManager.beginTransaction()
                .add(R.id.fragment_container, HomeFragment())
                .addToBackStack(null)
                .commit()
        }
    }

    fun openDetail(userId: String) {
        supportFragmentManager.beginTransaction()
            .replace(R.id.fragment_container, DetailFragment.newInstance(userId))
            .addToBackStack(null)
            .commit()
    }

    override fun onBackPressed() {
        if (supportFragmentManager.backStackEntryCount > 0) {
            supportFragmentManager.popBackStack()
        } else {
            super.onBackPressed()
        }
    }
}

class DetailFragment : Fragment() {
    companion object {
        fun newInstance(userId: String): DetailFragment {
            return DetailFragment().apply {
                arguments = Bundle().apply { putString("user_id", userId) }
            }
        }
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        val userId = arguments?.getString("user_id")
        Log.d("DetailFragment", "กำลังโหลดรายละเอียดผู้ใช้: $userId")
    }
}

Activity ใช้ supportFragmentManager เพื่อจัดการ fragments ธุรกรรม add() กับ BackStack รับประกันว่าเมื่อกดย้อนกลับ HomeFragment จะถูกกู้คืน openDetail() แทนที่ Fragment ปัจจุบันด้วย DetailFragment พร้อมอาร์กิวเมนต์ การตรวจสอบ savedInstanceState == null ป้องกันการทำซ้ำของ fragment เมื่อหมุนหน้าจอ

ตัวอย่างที่ 3: Fragment กับ LifecycleObserver และ StateFlow

การใช้ Flow และ StateFlow ใน Fragment กับ viewLifecycleOwner สำหรับการอัปเดต UI แบบรีแอกทีฟ

kotlin
class SearchFragment : Fragment() {
    private val viewModel: SearchViewModel by viewModels()
    private var binding: FragmentSearchBinding? = null

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View {
        binding = FragmentSearchBinding.inflate(inflater, container, false)
        return binding!!.root
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        binding?.searchButton?.setOnClickListener {
            viewModel.search(binding?.queryInput?.text.toString())
        }
        viewLifecycleOwner.lifecycleScope.launch {
            viewModel.searchResults.collectLatest { results ->
                Log.d("SearchFragment", "ผลการค้นหา: ${results.size}")
            }
        }
    }

    override fun onDestroyView() {
        super.onDestroyView()
        binding = null
    }
}

Fragment ใช้ View Binding เพื่อเข้าถึง View Coroutine viewLifecycleOwner.lifecycleScope.launch ถูกยกเลิกโดยอัตโนมัติเมื่อ View ถูกทำลาย Binding ถูกตั้งเป็น null ใน onDestroyView เพื่อป้องกันการรั่วไหล StateFlow รับประกันความสดของข้อมูลเมื่อ View ถูกสร้างใหม่

คำถามที่พบบ่อย

onViewCreated ต่างจาก onCreateView อย่างไร?

onCreateView สร้างและส่งคืน View หลักของ Fragment onViewCreated ถูกเรียกทันทีหลังจากการสร้าง View รับประกันว่า View ถูกเริ่มต้นอย่างสมบูรณ์และพร้อมสำหรับการกำหนดค่า (findViewById การสมัครรับ) Google แนะนำให้ขยายเลย์เอาต์ใน onCreateView เท่านั้น และทำการกำหนดค่า UI ทั้งหมดใน onViewCreated

Fragment ถูกทำลายจริงเมื่อไหร่ — ที่ onDestroy หรือ onDetach?

onDestroy — Fragment ถูกทำลายเป็นออบเจ็กต์ (ViewModel ถูกล้าง Coroutine ถูกยกเลิก) onDetach คือ callback สุดท้าย หลังจากนั้น Fragment หลุดจาก Activity ในทางปฏิบัติ ทรัพยากรทั้งหมดควรถูกปล่อยใน onDestroyView (View) และ onDestroy (Fragment) onDetach ใช้สำหรับทำความสะอาดการอ้างอิงถึง Activity

ทำไม Fragment หายไปหลังหมุนหน้าจอ?

Fragment หายไปถ้ามัน ไม่ได้ถูกเพิ่มไปยัง FragmentManager ผ่านธุรกรรม ที่มีการเก็บรักษาใน BackStack หรือถ้า Activity ไม่ได้กู้คืน FragmentManager ใน onCreate วิธีแก้ปัญหา: เพิ่ม Fragment โดยทางโปรแกรมผ่าน supportFragmentManager.beginTransaction().add() ใน onCreate ด้วยการตรวจสอบ savedInstanceState == null

Fragment สามารถอยู่ได้โดยไม่มี Activity หรือไม่?

ไม่ Fragment เชื่อมโยงกับ Activity ผ่าน FragmentManager เสมอ แม้เมื่อหมุนหน้าจอ Activity จะถูกสร้างใหม่และ Fragment จะถูกแนบกับ Activity ใหม่ การสร้าง Fragment นอก Activity เป็นไปไม่ได้ — ตัวสร้าง Fragment ต้องการตัวสร้างว่างสำหรับการกู้คืนโดยระบบ

Nested fragments คืออะไรและทำไมต้องใช้?

Nested fragments (fragments ที่ซ้อนกัน) คือ Fragments ภายใน Fragment อื่น ใช้สำหรับสร้างหน้าจอที่ซับซ้อน: แผงแท็บ แผงที่มีแท็บ master-detail Nested fragments จัดการโดย FragmentManager ลูก (childFragmentManager) Google แนะนำไม่ให้เกิน 2 ระดับของการซ้อนเพื่อหลีกเลี่ยงปัญหาด้านประสิทธิภาพ

สรุป

  • Fragment Lifecycle ประกอบด้วย 11 callback: onAttach → onCreate → onCreateView → onViewCreated → onStart → onResume → onPause → onStop → onDestroyView → onDestroy → onDetach
  • FragmentManager จัดการสถานะของ Fragment (INITIALIZED → CREATED → STARTED → RESUMED → DESTROYED) และ BackStack ของธุรกรรม
  • Fragment อยู่รอดจากการหมุนหน้าจอ — View ถูกทำลาย (onDestroyView) แต่ Fragment และ ViewModel ยังคงมีชีวิต
  • viewLifecycleOwner คือ Lifecycle แยกต่างหากสำหรับ View ของ Fragment จำเป็นสำหรับการสมัครรับ LiveData และ coroutine UI
  • การบันทึกสถานะ Fragment — ผ่าน onSaveInstanceState หรือ SavedStateHandle ใน ViewModel
  • ธุรกรรม Fragment ดำเนินการผ่าน FragmentManager ด้วย commit() (อะซิงโครนัส) หรือ commitNow() (ซิงโครนัส)
  • ตั้งค่า binding และการอ้างอิง View เป็น null ใน onDestroyView เสมอเพื่อป้องกันการรั่วไหลของหน่วยความจำ

เราจะพัฒนาแอปพลิเคชันบนมือถือแบบครบวงจร

IT Sectr สร้างแอปพลิเคชัน iOS และ Android สำหรับสตาร์ทอัพและธุรกิจตั้งแต่ปี 2017 เราจะให้คำแนะนำและเสนอวิธีแก้ปัญหาที่ดีที่สุดแก่คุณ

ปรึกษาโครงการ

อ่านเพิ่มเติม