การกำหนดค่าอุปกรณ์บางอย่างอาจเปลี่ยนแปลงขณะที่แอปทำงานอยู่ ซึ่งรวมถึงแต่ไม่จำกัดเพียงรายการต่อไปนี้
- ขนาดการแสดงผลของแอป
- การวางแนวหน้าจอ
- ขนาดและน้ำหนักของแบบอักษร
- ภาษา
- โหมดมืดกับโหมดสว่าง
- ความพร้อมใช้งานของแป้นพิมพ์
การเปลี่ยนแปลงการกําหนดค่าส่วนใหญ่เหล่านี้เกิดขึ้นเนื่องจากการโต้ตอบของผู้ใช้ เช่น การบิดหรือพับอุปกรณ์จะเปลี่ยนพื้นที่หน้าจอที่พร้อมใช้งานสำหรับแอปของคุณ ในทำนองเดียวกัน การเปลี่ยนแปลงการตั้งค่าอุปกรณ์ เช่น ขนาดแบบอักษร ภาษา หรือธีมที่ต้องการ จะเปลี่ยนค่าที่เกี่ยวข้องในออบเจ็กต์ Configuration
โดยปกติแล้ว พารามิเตอร์เหล่านี้จะต้องมีการเปลี่ยนแปลง UI ของแอปพลิเคชันมากพอที่แพลตฟอร์ม Android จะมีกลไกที่สร้างขึ้นเพื่อวัตถุประสงค์ดังกล่าวเมื่อเกิดการเปลี่ยนแปลง
กลไกนี้เป็นActivity
การจำลอง
การสร้างกิจกรรมขึ้นมาใหม่
ระบบจะสร้าง Activity
ขึ้นมาใหม่เมื่อมีการเปลี่ยนแปลงการกําหนดค่า โดยระบบจะเรียกใช้ onDestroy()
และทำลายอินสแตนซ์ Activity
ที่มีอยู่ จากนั้นจะสร้างอินสแตนซ์ใหม่โดยใช้ onCreate()
และอินสแตนซ์ Activity
ใหม่นี้จะเริ่มต้นด้วยการกำหนดค่าใหม่ที่อัปเดตแล้ว ซึ่งหมายความว่าระบบจะสร้าง UI ใหม่ด้วยการกำหนดค่าใหม่ด้วย
ลักษณะการทํางานใหม่นี้ช่วยให้แอปพลิเคชันปรับตัวเข้ากับการกําหนดค่าใหม่ได้โดยการโหลดแอปพลิเคชันอีกครั้งโดยอัตโนมัติด้วยทรัพยากรอื่นที่ตรงกับการกําหนดค่าอุปกรณ์ใหม่
ตัวอย่างกิจกรรมสันทนาการ
พิจารณา TextView
ที่แสดงชื่อแบบคงที่โดยใช้ android:text="@string/title"
ตามที่กําหนดไว้ในไฟล์ XML ของเลย์เอาต์ เมื่อสร้างมุมมองแล้ว ระบบจะตั้งค่าข้อความเพียงครั้งเดียวตามภาษาปัจจุบัน หากภาษามีการเปลี่ยนแปลง ระบบจะสร้างกิจกรรมขึ้นมาใหม่ ดังนั้น ระบบจะสร้างมุมมองขึ้นมาใหม่และเริ่มต้นค่าให้ถูกต้องตามภาษาใหม่ด้วย
การสร้างใหม่นี้จะล้างสถานะใดๆ ที่เก็บไว้เป็นช่องใน Activity
หรือใน Fragment
, View
หรือออบเจ็กต์อื่นๆ ที่มี เนื่องจากการสร้าง Activity
ใหม่จะสร้างอินสแตนซ์ Activity
และ UI ใหม่ทั้งหมด นอกจากนี้ Activity
เดิมจะไม่ปรากฏหรือใช้งานได้อีกต่อไป ดังนั้นการอ้างอิงที่เหลืออยู่หรือออบเจ็กต์ที่อยู่ใน Activity
ดังกล่าวจะล้าสมัย ซึ่งอาจทำให้เกิดข้อบกพร่อง การสูญเสียหน่วยความจำ และการขัดข้อง
ความคาดหวังของผู้ใช้
ผู้ใช้แอปคาดหวังว่าระบบจะเก็บสถานะไว้ หากผู้ใช้กรอกแบบฟอร์มและเปิดแอปอื่นในโหมดหลายหน้าต่างเพื่อดูข้อมูลอ้างอิง ประสบการณ์ของผู้ใช้จะไม่ดีหากผู้ใช้กลับไปที่แบบฟอร์มที่ล้างข้อมูลแล้วหรือไปยังส่วนอื่นในแอปโดยสิ้นเชิง ในฐานะนักพัฒนาแอป คุณต้องมอบประสบการณ์ที่สอดคล้องกันแก่ผู้ใช้ผ่านการเปลี่ยนแปลงการกำหนดค่าและการสร้างกิจกรรมอีกครั้ง
หากต้องการยืนยันว่าแอปพลิเคชันเก็บสถานะไว้หรือไม่ ให้ทำการดำเนินการที่ทำให้เกิดการเปลี่ยนแปลงการกำหนดค่าทั้งในขณะที่แอปทำงานอยู่เบื้องหน้าและขณะทำงานอยู่เบื้องหลัง การทำงานดังกล่าว ได้แก่:
- การหมุนอุปกรณ์
- เข้าสู่โหมดหลายหน้าต่าง
- การปรับขนาดแอปพลิเคชันขณะอยู่ในโหมดหลายหน้าต่างหรือหน้าต่างแบบอิสระ
- การพับอุปกรณ์แบบพับได้ที่มีหลายจอแสดงผล
- การเปลี่ยนธีมของระบบ เช่น โหมดมืดกับโหมดสว่าง
- การเปลี่ยนขนาดแบบอักษร
- การเปลี่ยนภาษาของระบบหรือแอป
- การเชื่อมต่อหรือยกเลิกการเชื่อมต่อแป้นพิมพ์ฮาร์ดแวร์
- การเชื่อมต่อหรือยกเลิกการเชื่อมต่อแท่นชาร์จ
คุณใช้แนวทางหลักๆ 3 วิธีเพื่อรักษาสถานะที่เกี่ยวข้องผ่านActivity
การสร้างใหม่ได้ การใช้รูปแบบใดจะขึ้นอยู่กับประเภทสถานะที่ต้องการเก็บรักษา ดังนี้
- การคงข้อมูลไว้ในเครื่องเพื่อจัดการการหยุดทำงานของกระบวนการสำหรับข้อมูลที่ซับซ้อนหรือมีขนาดใหญ่
พื้นที่เก็บข้อมูลในเครื่องแบบถาวรรวมถึงฐานข้อมูลหรือ
DataStore
- ออบเจ็กต์ที่เก็บไว้ เช่น อินสแตนซ์
ViewModel
เพื่อจัดการสถานะที่เกี่ยวข้องกับ UI ในหน่วยความจำขณะที่ผู้ใช้ใช้งานแอปอยู่ - สถานะอินสแตนซ์ที่บันทึกไว้เพื่อจัดการการสิ้นสุดกระบวนการที่ระบบเริ่มและเก็บสถานะชั่วคราวที่ขึ้นอยู่กับอินพุตหรือการนําทางของผู้ใช้
หากต้องการอ่านเกี่ยวกับ API ของรายการเหล่านี้โดยละเอียด รวมถึงกรณีที่ควรใช้แต่ละรายการ โปรดดูบันทึกสถานะ UI
จำกัดการสร้างกิจกรรมซ้ำ
คุณสามารถป้องกันการสร้างกิจกรรมใหม่โดยอัตโนมัติสำหรับการเปลี่ยนแปลงการกําหนดค่าบางอย่างได้
การสร้างActivity
ขึ้นมาใหม่จะส่งผลให้สร้าง UI ทั้งหมดขึ้นใหม่ รวมถึงออบเจ็กต์ที่มาจากActivity
คุณอาจมีเหตุผลที่ดีในการหลีกเลี่ยงการดำเนินการนี้ เช่น แอปอาจไม่จําเป็นต้องอัปเดตทรัพยากรในระหว่างการเปลี่ยนแปลงการกําหนดค่าบางอย่าง หรือคุณอาจมีข้อจํากัดด้านประสิทธิภาพ ในกรณีนี้ คุณประกาศได้ว่ากิจกรรมจะจัดการการเปลี่ยนแปลงการกําหนดค่าเองและป้องกันไม่ให้ระบบรีสตาร์ทกิจกรรม
หากต้องการปิดใช้การสร้างกิจกรรมอีกครั้งสําหรับการเปลี่ยนแปลงการกําหนดค่าบางอย่าง ให้เพิ่มประเภทการกําหนดค่าเป็น android:configChanges
ในรายการ <activity>
ในไฟล์ AndroidManifest.xml
ค่าที่เป็นไปได้จะปรากฏในเอกสารประกอบสำหรับแอตทริบิวต์ android:configChanges
โค้ดไฟล์ Manifest ต่อไปนี้จะปิดใช้การสร้างActivity
ใหม่สําหรับ MyActivity
เมื่อการวางแนวหน้าจอและความพร้อมใช้งานของแป้นพิมพ์มีการเปลี่ยนแปลง
<activity
android:name=".MyActivity"
android:configChanges="orientation|screenSize|screenLayout|keyboardHidden"
android:label="@string/app_name">
การเปลี่ยนแปลงการกําหนดค่าบางอย่างทําให้กิจกรรมเริ่มต้นใหม่เสมอ คุณปิดใช้ไม่ได้ เช่น คุณไม่สามารถปิดใช้การเปลี่ยนสีแบบไดนามิกที่เปิดตัวใน Android 12L (API ระดับ 32)
ตอบสนองต่อการเปลี่ยนแปลงการกําหนดค่าในระบบ View
ในระบบ View
เมื่อเกิดการเปลี่ยนแปลงการกําหนดค่าที่คุณปิดใช้การสร้าง Activity
ใหม่ กิจกรรมจะได้รับการเรียกใช้ Activity.onConfigurationChanged()
มุมมองที่แนบมาจะได้รับView.onConfigurationChanged()
ด้วย สําหรับการเปลี่ยนแปลงการกําหนดค่าที่คุณยังไม่ได้เพิ่มลงใน android:configChanges
ระบบจะสร้างกิจกรรมขึ้นมาใหม่ตามปกติ
เมธอดการเรียกกลับ onConfigurationChanged()
จะได้รับออบเจ็กต์ Configuration
ที่ระบุการกำหนดค่าอุปกรณ์ใหม่ อ่านช่องในออบเจ็กต์ Configuration
เพื่อดูการกำหนดค่าใหม่ หากต้องการทำการเปลี่ยนแปลงในภายหลัง ให้อัปเดตทรัพยากรที่ใช้ในอินเทอร์เฟซ เมื่อระบบเรียกใช้เมธอดนี้ ระบบจะอัปเดตออบเจ็กต์ Resources
ของกิจกรรมเพื่อแสดงผลทรัพยากรตามการกำหนดค่าใหม่ ซึ่งจะช่วยให้คุณรีเซ็ตองค์ประกอบของ UI ได้โดยไม่ต้องให้ระบบเริ่มกิจกรรมอีกครั้ง
ตัวอย่างเช่น การติดตั้งใช้งาน onConfigurationChanged()
ต่อไปนี้จะตรวจสอบว่ามีแป้นพิมพ์หรือไม่
Kotlin
override fun onConfigurationChanged(newConfig: Configuration) {
super.onConfigurationChanged(newConfig)
// Checks whether a keyboard is available
if (newConfig.keyboardHidden === Configuration.KEYBOARDHIDDEN_YES) {
Toast.makeText(this, "Keyboard available", Toast.LENGTH_SHORT).show()
} else if (newConfig.keyboardHidden === Configuration.KEYBOARDHIDDEN_NO) {
Toast.makeText(this, "No keyboard", Toast.LENGTH_SHORT).show()
}
}
Java
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
// Checks whether a keyboard is available
if (newConfig.keyboardHidden == Configuration.KEYBOARDHIDDEN_YES) {
Toast.makeText(this, "Keyboard available", Toast.LENGTH_SHORT).show();
} else if (newConfig.keyboardHidden == Configuration.KEYBOARDHIDDEN_NO){
Toast.makeText(this, "No keyboard", Toast.LENGTH_SHORT).show();
}
}
หากไม่จําเป็นต้องอัปเดตแอปพลิเคชันตามการเปลี่ยนแปลงการกําหนดค่าเหล่านี้ คุณก็ไม่ต้องติดตั้งใช้งาน onConfigurationChanged()
ในกรณีนี้ ระบบจะยังคงใช้ทรัพยากรทั้งหมดที่ใช้ก่อนการเปลี่ยนแปลงการกําหนดค่า และคุณเพียงแค่หลีกเลี่ยงการเริ่มกิจกรรมอีกครั้งเท่านั้น เช่น แอปทีวีอาจไม่ต้องการตอบสนองเมื่อเชื่อมต่อหรือถอดแป้นพิมพ์บลูทูธ
เก็บสถานะ
เมื่อใช้เทคนิคนี้ คุณต้องยังคงเก็บสถานะไว้ในระหว่างวงจรของกิจกรรมตามปกติ สาเหตุมีดังนี้
- การเปลี่ยนแปลงที่หลีกเลี่ยงไม่ได้: การเปลี่ยนแปลงการกําหนดค่าที่คุณป้องกันไม่ได้อาจทำให้แอปพลิเคชันรีสตาร์ท
- การสิ้นสุดการประมวลผล: แอปพลิเคชันต้องจัดการการสิ้นสุดการประมวลผลที่ระบบเริ่มได้ หากผู้ใช้ออกจากแอปพลิเคชันและแอปทำงานอยู่เบื้องหลัง ระบบอาจทำลายแอป
ตอบสนองต่อการเปลี่ยนแปลงการกําหนดค่าใน Jetpack Compose
Jetpack Compose ช่วยให้แอปตอบสนองต่อการเปลี่ยนแปลงการกำหนดค่าได้ง่ายขึ้น
อย่างไรก็ตาม หากคุณปิดใช้Activity
การสร้างใหม่สำหรับการเปลี่ยนแปลงการกำหนดค่าทั้งหมดที่เป็นไปได้ แอปของคุณยังคงต้องจัดการการเปลี่ยนแปลงการกำหนดค่าอย่างถูกต้อง
ออบเจ็กต์ Configuration
มีอยู่ในลําดับชั้น UI ขององค์ประกอบการเขียนที่มีองค์ประกอบ LocalConfiguration
เมื่อใดก็ตามที่มีการเปลี่ยนแปลง ฟังก์ชันแบบคอมโพสิเบิลที่อ่านจาก LocalConfiguration.current
จะคอมโพสใหม่ ดูข้อมูลเกี่ยวกับวิธีการทำงานขององค์ประกอบในเครื่องได้ที่ข้อมูลที่มีขอบเขตระดับท้องถิ่นด้วย CompositionLocal
ตัวอย่าง
ในตัวอย่างต่อไปนี้ คอมโพสิเบิลจะแสดงวันที่ในรูปแบบที่เฉพาะเจาะจง
คอมโพสิเบิลจะตอบสนองต่อการเปลี่ยนแปลงการกําหนดค่าภาษาของระบบโดยการเรียกใช้ ConfigurationCompat.getLocales()
ด้วย LocalConfiguration.current
@Composable
fun DateText(year: Int, dayOfYear: Int) {
val dateTimeFormatter = DateTimeFormatter.ofPattern(
"MMM dd",
ConfigurationCompat.getLocales(LocalConfiguration.current)[0]
)
Text(
dateTimeFormatter.format(LocalDate.ofYearDay(year, dayOfYear))
)
}
Activity
ที่โฮสต์โค้ด Compose ต้องเลือกไม่ใช้การเปลี่ยนแปลงการกำหนดค่าภาษาเพื่อหลีกเลี่ยงการสร้างActivity
ใหม่เมื่อภาษาเปลี่ยนแปลง โดยให้ตั้งค่า android:configChanges
เป็น locale|layoutDirection
การเปลี่ยนแปลงการกําหนดค่า: แนวคิดหลักและแนวทางปฏิบัติแนะนํา
แนวคิดสําคัญที่ควรทราบเมื่อทําการเปลี่ยนแปลงการกําหนดค่ามีดังนี้
- การกําหนดค่า: การกําหนดค่าอุปกรณ์กําหนดวิธีแสดง UI ต่อผู้ใช้ เช่น ขนาดการแสดงผลของแอป ภาษา หรือธีมของระบบ
- การเปลี่ยนแปลงการกําหนดค่า: การกําหนดค่าจะเปลี่ยนแปลงผ่านการโต้ตอบของผู้ใช้ เช่น ผู้ใช้อาจเปลี่ยนการตั้งค่าอุปกรณ์หรือวิธีโต้ตอบกับอุปกรณ์ คุณจะป้องกันการเปลี่ยนแปลงการกำหนดค่าไม่ได้
Activity
recreation: การเปลี่ยนแปลงการกําหนดค่าจะทําให้Activity
สร้างขึ้นใหม่โดยค่าเริ่มต้น นี่เป็นกลไกในตัวเพื่อเริ่มต้นสถานะแอปใหม่สําหรับการกําหนดค่าใหม่- การทำลาย
Activity
: การสร้างActivity
ใหม่จะทำให้ระบบทำลายอินสแตนซ์Activity
เดิมและสร้างอินสแตนซ์ใหม่ขึ้นมาแทน อินสแตนซ์เก่าจึงล้าสมัยไปแล้ว การอ้างอิงที่เหลืออยู่จะส่งผลให้หน่วยความจํารั่วไหล เกิดข้อบกพร่อง หรือข้อขัดข้อง - สถานะ: สถานะในอินสแตนซ์
Activity
เก่าไม่อยู่ในอินสแตนซ์Activity
ใหม่ เนื่องจากเป็นอินสแตนซ์ออบเจ็กต์ 2 รายการที่แตกต่างกัน เก็บรักษาสถานะของแอปและผู้ใช้ตามที่อธิบายไว้ในบันทึกสถานะ UI - เลือกไม่ใช้: การเลือกไม่ใช้การสร้างกิจกรรมอีกครั้งสําหรับการกําหนดค่าประเภทหนึ่งๆ อาจเป็นการเพิ่มประสิทธิภาพที่เป็นไปได้ แอปของคุณจึงต้องอัปเดตอย่างถูกต้องเพื่อตอบสนองต่อการกำหนดค่าใหม่
โปรดปฏิบัติตามแนวทางปฏิบัติแนะนำต่อไปนี้เพื่อให้ผู้ใช้ได้รับประสบการณ์การใช้งานที่ดี
- เตรียมพร้อมสำหรับการเปลี่ยนแปลงการกำหนดค่าบ่อยครั้ง: อย่าคิดว่าการเปลี่ยนแปลงการกำหนดค่านั้นเกิดขึ้นน้อยครั้งหรือไม่เกิดขึ้นเลย ไม่ว่า API ระดับใด รูปแบบใด หรือชุดเครื่องมือ UI ใดก็ตาม เมื่อผู้ใช้ทําการเปลี่ยนแปลงการกําหนดค่า ผู้ใช้คาดหวังว่าแอปจะอัปเดตและทํางานต่อไปอย่างถูกต้องกับการกําหนดค่าใหม่
- รักษาสถานะ: รักษาสถานะของผู้ใช้ไว้เมื่อเกิดการสร้าง
Activity
ขึ้นมาใหม่ เก็บรักษาสถานะตามที่อธิบายไว้ในบันทึกสถานะ UI - หลีกเลี่ยงการเลือกไม่ใช้เพื่อแก้ปัญหาอย่างรวดเร็ว: อย่าเลือกไม่ใช้การสร้าง
Activity
ใหม่เป็นทางลัดเพื่อหลีกเลี่ยงการสูญเสียสถานะ การเลือกไม่ใช้การสร้างกิจกรรมใหม่หมายความว่าคุณต้องดำเนินการตามที่สัญญาไว้ว่าจะจัดการกับการเปลี่ยนแปลง และคุณอาจยังสูญเสียสถานะเนื่องจากมีการสร้างActivity
ใหม่จากการเปลี่ยนแปลงการกําหนดค่าอื่นๆ การสิ้นสุดกระบวนการ หรือปิดแอป คุณจะปิดใช้การสร้างActivity
ใหม่ทั้งหมดไม่ได้ เก็บรักษาสถานะตามที่อธิบายไว้ในบันทึกสถานะ UI - อย่าหลีกเลี่ยงการเปลี่ยนแปลงการกำหนดค่า: อย่าจำกัดการวางแนว อัตราส่วนภาพ หรือความสามารถในการปรับขนาดเพื่อหลีกเลี่ยงการเปลี่ยนแปลงการกำหนดค่าและ
Activity
การสร้างใหม่ ซึ่งส่งผลเสียต่อผู้ใช้ที่ต้องการใช้แอปของคุณในลักษณะที่ต้องการ
จัดการการเปลี่ยนแปลงการกำหนดค่าตามขนาด
การเปลี่ยนแปลงการกำหนดค่าตามขนาดอาจเกิดขึ้นได้ทุกเมื่อ และมีโอกาสมากขึ้นเมื่อแอปทำงานบนอุปกรณ์หน้าจอขนาดใหญ่ที่ผู้ใช้สามารถเข้าสู่โหมดหลายหน้าต่าง โดยผู้ใช้คาดหวังว่าแอปของคุณจะทํางานได้ดีในสภาพแวดล้อมดังกล่าว
การเปลี่ยนแปลงขนาดโดยทั่วไปมี 2 ประเภท ได้แก่ การเปลี่ยนแปลงที่มีนัยสำคัญและการเปลี่ยนแปลงที่ไม่มีนัยสำคัญ การเปลี่ยนแปลงขนาดที่สำคัญคือการเปลี่ยนแปลงที่ทรัพยากรทางเลือกชุดอื่นมีผลกับการกำหนดค่าใหม่เนื่องจากขนาดหน้าจอแตกต่างกัน เช่น ความกว้าง ความสูง หรือความกว้างน้อยที่สุด แหล่งข้อมูลเหล่านี้รวมถึงแหล่งข้อมูลที่แอปกำหนดเองและแหล่งข้อมูลจากไลบรารีของแอป
จำกัดการสร้างกิจกรรมใหม่สำหรับการเปลี่ยนแปลงการกำหนดค่าตามขนาด
เมื่อปิดใช้การสร้าง Activity
อีกครั้งสำหรับการเปลี่ยนแปลงการกำหนดค่าตามขนาด ระบบจะไม่สร้าง Activity
ขึ้นมาใหม่ แต่จะได้รับคําเรียกให้ดำเนินการไปที่ Activity.onConfigurationChanged()
แทน มุมมองที่แนบมาจะได้รับสายเรียกไปที่ View.onConfigurationChanged()
ระบบจะปิดใช้การสร้างActivity
ใหม่สำหรับการเปลี่ยนแปลงการกำหนดค่าตามขนาดเมื่อคุณมีandroid:configChanges="screenSize|smallestScreenSize|orientation|screenLayout"
ในไฟล์ Manifest
อนุญาตให้สร้างกิจกรรมใหม่สําหรับการเปลี่ยนแปลงการกําหนดค่าตามขนาด
ใน Android 7.0 (API ระดับ 24) ขึ้นไป Activity
การสร้างใหม่จะเกิดขึ้นเฉพาะเมื่อมีการเปลี่ยนแปลงการกำหนดค่าตามขนาด หากการเปลี่ยนแปลงขนาดมีนัยสำคัญ เมื่อระบบไม่สร้าง Activity
ขึ้นมาใหม่เนื่องจากมีขนาดใหญ่ไม่พอ ระบบอาจเรียกใช้ Activity.onConfigurationChanged()
และ View.onConfigurationChanged()
แทน
ข้อควรระวังบางอย่างเกี่ยวกับ Activity
และ View
callbacks เมื่อไม่ได้สร้าง Activity
ขึ้นมาใหม่มีดังนี้
- ใน Android 11 (API ระดับ 30) ถึง Android 13 (API ระดับ 33) ระบบจะไม่เรียกใช้
Activity.onConfigurationChanged()
- ปัญหาที่ทราบคือ
View.onConfigurationChanged()
อาจไม่เรียกใช้ในบางกรณีใน Android 12L (API ระดับ 32) และ Android 13 เวอร์ชันแรกๆ (API ระดับ 33) ดูข้อมูลเพิ่มเติมได้ที่ปัญหาสาธารณะนี้ ปัญหานี้ได้รับการแก้ไขแล้วใน Android 13 เวอร์ชันที่ใหม่กว่าและ Android 14
สําหรับโค้ดที่ขึ้นอยู่กับการฟังการเปลี่ยนแปลงการกําหนดค่าตามขนาด เราขอแนะนําให้ใช้ยูทิลิตี View
ที่มีView.onConfigurationChanged()
ที่ลบล้างแทนการอาศัยการสร้าง Activity
ใหม่หรือActivity.onConfigurationChanged()