จัดการการเปลี่ยนแปลงการกำหนดค่า

การกำหนดค่าอุปกรณ์บางอย่างอาจเปลี่ยนแปลงขณะที่แอปทำงานอยู่ ซึ่งรวมถึงแต่ไม่จำกัดเพียงรายการต่อไปนี้

  • ขนาดการแสดงผลของแอป
  • การวางแนวหน้าจอ
  • ขนาดและน้ำหนักของแบบอักษร
  • ภาษา
  • โหมดมืดกับโหมดสว่าง
  • ความพร้อมใช้งานของแป้นพิมพ์

การเปลี่ยนแปลงการกําหนดค่าส่วนใหญ่เหล่านี้เกิดขึ้นเนื่องจากการโต้ตอบของผู้ใช้ เช่น การบิดหรือพับอุปกรณ์จะเปลี่ยนพื้นที่หน้าจอที่พร้อมใช้งานสำหรับแอปของคุณ ในทำนองเดียวกัน การเปลี่ยนแปลงการตั้งค่าอุปกรณ์ เช่น ขนาดแบบอักษร ภาษา หรือธีมที่ต้องการ จะเปลี่ยนค่าที่เกี่ยวข้องในออบเจ็กต์ 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()