onRestart — เมธอดของวงจรชีวิต Activity ใน Android ซึ่งถูกเรียกโดยระบบก่อนที่ Activity จะกลับจากสถานะ Stopped ไปยังสถานะ Started onRestart บ่งชี้ว่า Activity ที่ถูกซ่อนโดยหน้าจออื่นหรือถูกย่อลงพื้นหลังก่อนหน้านี้ กำลังกลับมามองเห็นได้อีกครั้งสำหรับผู้ใช้ ใน onRestart นักพัฒนาจะอัปเดตข้อมูลที่ล้าสมัย โหลดรายการใหม่ และคืนค่าสถานะ UI ที่อาจเปลี่ยนแปลงไปในขณะที่ Activity มองไม่เห็น ตามข้อมูลของ Google Android Vitals (2025) แอปที่ใช้ onRestart เพื่ออัปเดตข้อมูลแสดงกรณีการแสดงข้อมูลที่ไม่ถูกต้องน้อยลง 25% เมื่อกลับมาที่หน้าจอ เอกสารประกอบ Android Developers อธิบายว่า onRestart เป็นขั้นตอนเตรียมการก่อนที่ Activity จะปรากฏบนหน้าจออีกครั้ง
ประเด็นสำคัญ
onRestart — เมธอด callback ที่ Android เรียกก่อน onStart อย่างเคร่งครัดเมื่อ Activity กลับจากสถานะ Stopped ที่มองไม่เห็นกลับมามองเห็นได้ เมธอดนี้มีความพิเศษตรงที่จะถูกเรียกเมื่อ Activity ถูกแสดงอีกครั้งเท่านั้น — ในระหว่างการสร้างอินสแตนซ์ครั้งแรก ลำดับจะเริ่มต้นด้วย onCreate โดยข้าม onRestart วงจรที่สมบูรณ์: onCreate → onStart → onResume (การเปิดตัวครั้งแรก) หรือ onRestart → onStart → onResume (การแสดงครั้งถัดไป)
จากมุมมองของระบบ Android onRestart คือการเพิ่มประสิทธิภาพที่ช่วยให้ Activity เตรียมพร้อมสำหรับการกลับมา: อัปเดตข้อมูลจาก repository ซิงโครไนซ์สถานะ UI ตรวจสอบการเชื่อมต่อเครือข่าย แตกต่างจาก onResume ซึ่งถูกเรียกทุกครั้งที่ Activity ได้รับโฟกัส (รวมถึงเมื่อกลับจากกล่องโต้ตอบหรือเมนูระบบ) onRestart จะถูกเรียกเฉพาะในระหว่างรอบการซ่อนและกลับที่สมบูรณ์เท่านั้น ทำให้ onRestart เป็นสถานที่ที่เหมาะสำหรับการดำเนินการอัปเดต “หนัก” ที่ไม่จำเป็นในระหว่างการสูญเสียโฟกัสบางส่วน
ตามข้อกำหนดวงจรชีวิต Activity ของ Android ช่วงเวลาระหว่าง onStop และ onRestart อาจมีตั้งแต่ไม่กี่วินาที (ผู้ใช้สลับอย่างรวดเร็ว) ไปจนถึงหลายชั่วโมง (แอปอยู่ในพื้นหลังและผู้ใช้กลับมา) ในช่วงเวลานี้ ข้อมูลในแหล่งข้อมูลระยะไกล (API, DB) อาจเปลี่ยนแปลงไป ดังนั้น onRestart จึงเป็นจุดธรรมชาติสำหรับการตรวจสอบความสดใหม่
onRestart จะถูกเรียกเมื่อ Activity กลับจากสถานะ Stopped เท่านั้น ซึ่ง Activity เข้าสู่หลังจากเรียก onStop ด้านล่างนี้คือสถานการณ์ทั้งหมดที่นำไปสู่ onRestart
สถานการณ์การเรียก onRestart:
เมื่อใดที่ onRestart จะไม่ถูกเรียก: ระหว่างการหมุนหน้าจอ (Activity ถูกทำลายและสร้างขึ้นใหม่ผ่าน onCreate) เมื่อกลับจากกล่องโต้ตอบ (Activity ไม่เข้าสู่ onStop มีเพียง onPause → onResume) ระหว่าง process death (Activity ถูกสร้างขึ้นใหม่)
onRestart และ onCreate เป็นสองแนวทางที่แตกต่างกันในการคืนค่า Activity การเลือกระหว่างทั้งสองขึ้นอยู่กับว่า Activity ถูกทำลายอย่างสมบูรณ์หรือถูกซ่อนไว้เท่านั้น
| ลักษณะ | onRestart | onCreate |
|---|---|---|
| เมื่อถูกเรียก | Activity กลับจาก Stopped | Activity ถูกสร้างขึ้นครั้งแรกหรือหลังจากถูกทำลาย |
| สถานะถูกเก็บรักษา | ใช่ — ViewModel และฟิลด์ยังมีชีวิต | ไม่ — ทุกอย่างถูกสร้างขึ้นใหม่ |
| Bundle | ไม่ถูกส่ง | ถูกส่ง (savedInstanceState) |
| การดำเนินการทั่วไป | อัปเดตข้อมูล, รีเฟรช UI | การเริ่มต้น View, การสมัครรับ LiveData |
| ความถี่ในการเรียก | ทุกครั้งเมื่อกลับมา | ครั้งเดียวหรือหลังจากการทำลาย |
กฎการเลือก: ทำการเริ่มต้น View และสมัครรับ LiveData/StateFlow ใน onCreate (หรือ onViewCreated สำหรับ Fragment) การอัปเดตข้อมูล การโหลดรายการใหม่ และการตรวจสอบสถานะ — ใน onRestart หากข้อมูลถูกโหลดผ่าน ViewModel onRestart สามารถเรียกเมธอด refresh() บน ViewModel และ View จะสมัครรับข้อมูลที่อัปเดตผ่านสตรีมแบบรีแอกทีฟ
Google แนะนำ: อย่าทำซ้ำตรรกะของ onCreate ใน onRestart แยกเมธอด refresh() ใน ViewModel ที่โหลดข้อมูลปัจจุบัน และเรียกพวกมันใน onRestart ซึ่งจะรักษาสถาปัตยกรรม MVVM ที่สะอาดและกำจัดการทำซ้ำโค้ด
onRestart เป็นสถานที่ที่เหมาะสำหรับการดำเนินการที่ควรทำทุกครั้งที่กลับมาที่หน้าจอ แต่ไม่จำเป็นในการเปิดครั้งแรก นี่คือสถานการณ์ทั่วไป:
viewModel.refreshItems() ใน onRestartสิ่งที่ไม่ควรทำใน onRestart: อย่าเริ่มต้น Views ใหม่ — พวกมันยังมีชีวิตอยู่เพราะ Activity ไม่ได้ถูกทำลาย อย่าสมัครรับ LiveData ซ้ำ — การสมัครใน onCreate ยังมีชีวิตอยู่ อย่าสร้าง Fragments ใหม่ — พวกมันอยู่ใน FragmentManager แล้ว
ข้อยกเว้นที่สำคัญที่สุด: onRestart จะไม่ถูกเรียกหากกระบวนการของแอปถูกฆ่าโดยระบบ นี่เป็นประเด็นสำคัญที่นักพัฒนามักมองข้ามเมื่อพึ่งพา onRestart สำหรับการคืนค่าสถานะ
ระหว่าง process death:
วิธีป้องกัน: บันทึกสถานะวิกฤตเสมอใน onSaveInstanceState(Bundle) (เรียกก่อน onStop) หรือใช้ SavedStateHandle ใน ViewModel ใน onCreate ตรวจสอบ savedInstanceState: ถ้าไม่เป็น null ให้คืนค่าสถานะจาก Bundle ถ้าเป็น null ให้โหลดข้อมูลใหม่
ตาม Google Android Vitals ประมาณ 7% ของการกลับไปยัง Activity หลังจากอยู่ในพื้นหลังเป็นเวลานานเกิดขึ้นหลังจาก process death ซึ่งหมายความว่าทุก ๆ Activity ที่ 15 ที่ควรเรียก onRestart จริง ๆ แล้วผ่าน onCreate การละเลยสถานการณ์นี้เป็นหนึ่งในสาเหตุหลักของบั๊ก “หน้าจอว่างหลังจากกลับมา”
Activity เรียก viewModel.refreshTasks() ใน onRestart เพื่ออัปเดตรายการงานหลังจากกลับจากหน้าจอแก้ไข
class TaskListActivity : AppCompatActivity() {
private val viewModel: TaskViewModel by viewModels()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_task_list)
viewModel.tasks.observe(this) { tasks ->
Log.d("TaskList", "ได้รับ ${tasks.size} งาน")
}
}
override fun onRestart() {
super.onRestart()
Log.d("TaskList", "onRestart: กำลังอัปเดตรายการงาน")
viewModel.refreshTasks()
}
}
class TaskViewModel : ViewModel() {
private val _tasks = MutableLiveData<List<Task>>()
val tasks: LiveData<List<Task>> get() = _tasks
fun refreshTasks() {
viewModelScope.launch {
_tasks.value = TaskRepository().getAllTasks()
}
}
}
ViewModel.refreshTasks() โหลดข้อมูลปัจจุบันจาก repository LiveData จะแจ้ง Activity โดยอัตโนมัติเกี่ยวกับการเปลี่ยนแปลงข้อมูล — UI อัปเดตโดยไม่ต้องใช้โค้ดเพิ่มเติม onRestart ไม่ได้สร้างการสมัครใหม่ — มันถูกตั้งค่าไว้แล้วใน onCreate
Activity ตรวจสอบความถูกต้องของโทเค็นเมื่อกลับมาและเปลี่ยนเส้นทางไปยังหน้าเข้าสู่ระบบหากจำเป็น
class ProfileActivity : AppCompatActivity() {
private val authManager = AuthManager()
private val launcher = registerForActivityResult(
ActivityResultContracts.StartActivityForResult()
) { Log.d("Profile", "กลับจากหน้าจอเข้าสู่ระบบ") }
override fun onRestart() {
super.onRestart()
if (!authManager.isTokenValid()) {
Log.d("Profile", "โทเค็นหมดอายุ — กำลังเปลี่ยนเส้นทางไปยังหน้าเข้าสู่ระบบ")
launcher.launch(Intent(this, LoginActivity::class.java))
}
}
}
class AuthManager {
fun isTokenValid(): Boolean {
val expiry = SharedPreferencesManager().getTokenExpiry()
return System.currentTimeMillis() < expiry
}
}
หากผู้ใช้ย่อแอปเป็นเวลานานและกลับมาหลังจากโทเค็นหมดอายุ onRestart จะเปลี่ยนเส้นทางไปยังหน้าจอเข้าสู่ระบบ ซึ่งป้องกันข้อผิดพลาด API เมื่อพยายามทำคำขอด้วยโทเค็นที่หมดอายุ หมายเหตุ: การตรวจสอบอยู่ใน onRestart ไม่ใช่ onResume เพื่อหลีกเลี่ยงการตรวจสอบที่ไม่จำเป็นเมื่อกลับจากกล่องโต้ตอบ
Fragment ใช้ onRestart ผ่าน LifecycleObserver เพื่ออัปเดตข้อมูล
class FeedFragment : Fragment() {
private val viewModel: FeedViewModel by viewModels()
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
viewLifecycleOwner.lifecycle.addObserver(object : LifecycleObserver {
@OnLifecycleEvent(Lifecycle.Event.ON_RESTART)
fun onRestart() {
Log.d("FeedFragment", "onRestart ผ่าน LifecycleObserver")
viewModel.refreshFeed()
}
})
}
}
แทนที่จะแทนที่ onRestart ใน Fragment จะใช้ LifecycleObserver — วิธีการที่ยืดหยุ่นกว่าที่ช่วยให้เพิ่มตรรกะเหตุการณ์วงจรชีวิตโดยไม่ต้องสืบทอด ViewLifecycleOwner รับประกันว่า observer อยู่ในขอบเขตของ View (มันไม่มีอายุยืนกว่า onDestroyView)
คำถามที่พบบ่อย
onResume จะถูกเรียกทุกครั้งที่ Activity ได้รับโฟกัส — รวมถึงเมื่อกลับจากกล่องโต้ตอบหรือเมนูระบบ (Activity ไม่ได้เข้าสู่ onStop) onRestart จะถูกเรียกเมื่อกลับจากสถานะ Stopped เท่านั้น เมื่อ Activity ถูกซ่อนอย่างสมบูรณ์ onRestart เป็นเหตุการณ์ที่แคบกว่าสำหรับการอัปเดต “หนัก” ในขณะที่ onResume สำหรับการดำเนินการเบา (เปลี่ยนชื่อเรื่อง อัปเดตเวลา)
ไม่ ไม่ได้ onRestart เป็นเมธอดคู่กับ onStop: onRestart จะถูกเรียกหลังจาก Activity ผ่าน onStop เท่านั้น หาก Activity ไม่ได้เข้าสู่ onStop (เช่น เปิดกล่องโต้ตอบไว้) เมื่อกลับมา onRestart จะไม่ถูกเรียก — มีเพียง onResume
กด Home (ปุ่มบ้าน) ในอีมูเลเตอร์ — Activity จะย่อและได้รับ onStop จากนั้นเปิดแอปผ่านแอปล่าสุดหรือตัวเรียกใช้ — Activity จะได้รับ onRestart → onStart → onResume สำหรับการดีบัก ให้ใช้ Debug พร้อมจุดพักใน onRestart หรือ Log.d พร้อมแท็ก Activity
ข้อยกเว้นที่ไม่ถูกจับใน onRestart จะทำให้เกิด Force Close ระบบไม่จับข้อยกเว้นใน callbacks ของวงจรชีวิต หากใน onRestart ดำเนินการที่อาจทำให้เกิดข้อยกเว้น (คำขอเครือข่ายโดยไม่มี try-catch การทำงานกับ View ที่เป็น null) ให้ห่อพวกมันใน try-catch
ไม่ onRestart จะถูกเรียกสำหรับ Activity ที่มีชีวิตที่กำลังกลับจากสถานะ Stopped เท่านั้น isFinishing() ใน onRestart จะเป็น false เสมอ การตรวจสอบ isFinishing() มีความหมายใน onPause (การบันทึกข้อมูล) และ onDestroy (การแยกความแตกต่างระหว่างการสร้างใหม่และการสิ้นสุด)
สรุป
เราจะพัฒนาแอปพลิเคชันบนมือถือแบบครบวงจร
IT Sectr สร้างแอปพลิเคชัน iOS และ Android สำหรับสตาร์ทอัพและธุรกิจตั้งแต่ปี 2017 เราจะให้คำแนะนำและเสนอวิธีแก้ปัญหาที่ดีที่สุดแก่คุณ